将Entity Framework与抽象类一起使用

时间:2011-04-20 07:07:08

标签: c# entity-framework abstract-class

有一个非常有趣的情况,似乎无法在反射,继承和泛型的网络上找到任何具体的东西。

首先:

我有一个基础抽象分类,名为:

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的一种类型,但是,如果我将ret值检查为:<返回类型,如果添加到监视器中,则返回List,如果: / p>

if (ret is IEnumerable<T>)

它忽略了支票。

如果我改变

public List<City> GetAllMajorCities() {}

public List<ItemBase> GetAllMajorCities() {}

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

我完全被难住了。

任何想法,建议都将不胜感激。

谢谢,

埃里克

3 个答案:

答案 0 :(得分:3)

您是否可以使用Framework 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添加到List<Item>。但是,显然cities.Add(new Person());无效(因为cities的“真实”(=静态)类型为List<City>)。因此,List<Item>永远不能是List<City>的超类型。

您无法将项目添加到IEnumerable,这就是 IEnumerable<City>IEnumerable<Item>之间的子类型关系的原因(但仅限于.net 4.0,如上所述)

答案 1 :(得分:1)

您可以尝试这样的事情:

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

答案 2 :(得分:1)

首先,这是错误的:

Type classType = className.GetType();

此构造将生成className的{​​{1}}类型,但不会生成名称存储在String中的类型。

更好,更类型安全的方式是:

className

更新:如果在调用public IEnumerable<TItem> InvokeGenericMethod<TItem, TContainer>(...) where TItem : ItemBase where TContainer : class, new() { TContainer container = new TContainer(); ... } 的地方静态地不知道TContainer类型,请查看静态 Type.GetType方法从其字符串名称中解析实际名称。在最简单的情况下,Type.GetType(String)方法访问您的类型的程序集限定名称,例如InvokeGenericMethod