使用实体框架和抽象类

本文关键字:抽象类 框架 实体 | 更新日期: 2023-09-27 17:50:33

有一个非常有趣的情况,似乎在网上找不到任何关于反射,继承和泛型的具体内容。

开头:

我有一个基本抽象类,叫做:

public abstract class ItemBase
{
     // default properties
}

ItemBase然后成为一个名为Item的抽象实体的超类:

public abstract class Item
{
    // some extra properties
}

这背后的思想是构造将继承Item的实体,并设置额外的属性:

public partial class City : Item {}

现在,在测试方法中,我试图使用反射来调用传递的实体上的方法,并返回任何数据,以任何形式,从方法返回。

假设,出于测试目的,我们在State中有一个方法,它返回所有主要城市的集合:

public List<City> GetAllMajorCities() {}

在我的存根中,我可能有一个测试来获得所有城市:

List<Item> cities = this.InvokeGenericMethod<Item>("State", "GetAllMajorCities", args);

然后InvokeGenericMethod(string, string, object[] args)看起来像:

public IEnumerable<T> InvokeGenericMethod<Item>(string className, string methodName, object[] args)
{
     Type classType = className.GetType(); // to get the class to create an instance of
     object classObj = Activator.CreateInstance(classType);
     object ret = classType.InvokeMember(methodName, BindingFlags.InvokeMethod, null, classObj, args);
}

理论上,从给出的例子来看,"ret"的值应该是IEnumerable类型,然而,返回类型,如果添加到监视来调查,返回List,如果我检查ret值为:

if (ret is IEnumerable<T>)

忽略检查

如果我改变

public List<City> GetAllMajorCities() {}

public List<ItemBase> GetAllMajorCities() {}

它似乎坚持继承,并允许我将其强制转换为IEnumberable。

我完全被难住了。

如有任何意见、建议,不胜感激。

谢谢,埃里克

使用实体框架和抽象类

是否有可能使用框架3.5?泛型协逆变是在。net 4.0中引入的。因此,以下内容在框架3.5中是不可能的:

class ItemBase { }
class Item : ItemBase { }
class City : Item { }
class Program
{
    static void Main(string[] args)
    {
        IEnumerable<City> cities = new List<City>();
        IEnumerable<Item> items = cities;  // Compile error here. IEnumerable<Item> is not a supertype of IEnumerable<City>.
    }
}

请注意,以下(这是你试图实现的)甚至不能在。net 4.0中工作:

List<Item> cities = new List<City>();

为什么不行?因为一定有可能将任意的Item s加到List<Item>中。但是,显然,cities.Add(new Person());不能工作(因为cities的"真实"(=静态)类型是List<City>)。因此,List<Item>永远不能是List<City>的超类型。

不能向IEnumerable中添加项,这就是为什么IEnumerable<City>IEnumerable<Item>之间存在子类型关系(但仅在。net 4.0中,如上所述)。

你可以尝试这样做:

        Type type = ret.GetType();
        Type listType = typeof(IEnumerable<T>);
        if (type == listType || type.IsSubclassOf(listType))
        {
            //
        }

首先,这是错误的:

Type classType = className.GetType();

这个构造将产生className的类型,即String,而不是名称存储在className中的类型。

一个更好的、更类型安全的方法是:

public IEnumerable<TItem> InvokeGenericMethod<TItem, TContainer>(...)
    where TItem : ItemBase
    where TContainer : class, new()
{
    TContainer container = new TContainer();
    ...
}

Update:如果TContainer类型在调用InvokeGenericMethod的地方不静态,请查看static Type.GetType方法,以从其字符串名称解析实际名称。在最简单的情况下,Type.GetType(String)方法访问您的类型的程序集限定名,例如"MyNamespace.City, MyAssembly"