泛型方法和访问具体实例属性

本文关键字:实例 属性 访问 泛型方法 | 更新日期: 2023-09-27 18:34:26

我有这些类(只是一个例子(:

/* Data classes */
public class Data
{
    public int Id { get; set; }
    ...
}
public InfoData<TInfo> : Data
    where TInfo: InfoBase
{
    public TInfo Info { get; set; }
    ...
}
/* Info classes */
// ABSTRACT
public abstract class InfoBase
{
    public int Id { get; set; }
    ...
}
public class ExtraInfo : InfoBase
{
    public IList<InfoBase> Related { get; set; }
}
// + other InfoBase inherited types

然后我有一个使用 Data(或任何继承的类型实例(但必须读取作为参数传递的实际对象实例的其他属性的方法:

TData Add<TData>(TData data)
    where TData: Data
{
    TData result = Get(
        data.Id,
        ...
        // how do I get to this one?
        data.Related[0].Id
    );
}

我可以访问所有类属性Data但是如何访问实际实例的其他属性,因为我不能只转换为类似

data as InfoData<InfoBase>

因为InfoBase是抽象的,我也不能用一些继承的非抽象类型来改变抽象泛型,因为需要考虑太多......

问题

  1. 如果很少有继承类拥有Related属性,我如何访问它?
  2. 有没有更好的方法来实现我的方法?

泛型方法和访问具体实例属性

转换为抽象应该没有问题,您还可以添加接口定义并让您的类继承它们,例如:

public interface IRelated{
    IList<InfoBase>Related {get; set;}
}
public class ExtraInfo : InfoBase, IRelated
{
    public IList<InfoBase> Related { get; set; }
}
public class OtherInfo:IRelated{
    public IList<InfoBase> Related { get; set; }
}

并强制转换为接口而不是类:

ExtraInfo i = new ExtraInfo(){ Id = 5 };
var p = (InfoBase)i;
var q = (IRelated)i;
q.Related.Add(new ExtraInfo());

但是我可以在您的代码中看到其他问题:在 Add 方法中,您错误地键入了属性:

data.Related.Id

因为数据。相关返回 InfoBase 的 IList,而不是 InfoBase 类本身。

编辑:

您必须更清楚地了解您希望从相关(或什么是获取参数列表(中获得什么。

编辑 2:

下面是适合您的添加方法代码:

TData Add<TData>(TData data) where TData:Data
{
    var infoBase = data as InfoBase; //or IRelated as in my earlier samples
    TData result;
    if (infoBase != null)
    {
        result = Get(data.id, infoBase.Related[0].Id); //you can also use infoBase.Id as first param
    }
    else
    {
        result = Get(data.id, null); //whatever you need to pass to the method if there is no related item
    }
}

编辑3:

这是工作代码:

public class Data
{
    public int Id { get; set; }
    //...
}
public class InfoData<TInfo> : Data
    where TInfo: InfoBase
{
    public TInfo Info { get; set; }
    //...
}
/* Info classes */
// ABSTRACT
public abstract class InfoBase
{
    public int Id { get; set; }
    //  ...
}
public interface IRelated
{
    IList<InfoBase> Related {get; set;}
}
public class ExtraInfo : InfoBase, IRelated
{
    public IList<InfoBase> Related { get; set; }
}
public class OtherInfo : InfoBase, IRelated
{
    public IList<InfoBase> Related { get; set; }
}
...
class MainClass
{
    public static TData Get<TData>(int id, int? related)
        where TData: Data
    {
        Console.WriteLine("id: {0}, related:{1}", id, related);
        return (TData)null;
    }
    public static TData Add<TData>(TData data)
        where TData: Data
    {
        return Get<TData>(data.Id,null);
    }
    public static TData Add<TData, TInfo>(TData data)
        where TData: InfoData<TInfo>
        where TInfo: InfoBase
    {
        var infoBase = data.Info as IRelated;
        if (infoBase == null)
            return Get<TData>(data.Id, null);
        return Get<TData>(data.Id, infoBase.Related[0].Id);
    }
    public static void Main(string[] args) {
        var i = new ExtraInfo {
            Id = 5,
            Related = new List<InfoBase> { new ExtraInfo { Id = 1 }}
        };
        var data = new InfoData<ExtraInfo> { Id = 100, Info = i };
        var result1 = Add<InfoData<ExtraInfo>, ExtraInfo>(data);
        var result2 = Add(data);
    }
}

但。。。整个代码看起来不太好:)

有几个可能的改进:

  • 您可以将 Add 方法移动到类 Data 中,然后重写
  • 您可以将相关的 Id 传递到 add 方法中,而不是传递整个对象
  • 您可以重新考虑域并检查是否真的需要如此多的重载。