使用抽象类型的反射从表中获取实体

时间:2009-01-13 14:17:31

标签: c# linq abstraction

好的,我有一个名为Product的抽象类。我有3个名为Items,Kits和Packages的表,它们实现了Product。 Product有一个公共属性,用于公开对象的主键。

那说我有一张表格,我传递了一个产品。我想从新的datacontext中取出该产品,而不必编写一个反映它的类型的大开关来获得正确的表格。

我想做类似这样的事情但是演员阵容不会接受foo。

public BuilderInclusionsForm(Product p) : this()
        {            
            Type foo = p.GetType();
            product = db2.GetTable(p.GetType()).Cast<foo>().SingleOrDefault(a => 
                a.ProductID == p.ProductID);

或者这个:

public BuilderInclusionsForm(Product p) : this()
        {            
            Type foo = p.GetType();
            product = db2.GetTable(p.GetType()).OfType<foo>().SingleOrDefault(a => 
                a.ProductID == p.ProductID);   

2 个答案:

答案 0 :(得分:5)

不,因为必须在编译时知道type参数才能出现在源代码中。

您可以在产品类型中创建BuilderInclusionsForm泛型,也可以编写如下通用方法:

private static T FindProduct<T>(T product) where T : Product
{
    return db2.GetTable(typeof(T))
                     .OfType<T>()
                     .SingleOrDefault(a => a.ProductID == p.ProductID);
}

然后用反射调用它:

public BuilderInclusionsForm(Product p) : this()
{            
    MethodInfo method = typeof(BuilderInclusionsForm).GetMethod("FindProduct",
         BindingFlags.Static | BindingFlags.NonPublic);
    MethodInfo concrete = method.MakeGenericMethod(new Type[] { p.GetType() });
    product = (Product) concrete.Invoke(null, new object[] { p });
}

(显然你可以缓存方法的开放形式。)

不好,但应该有效。我怀疑将BuilderInclusionsForm设为通用会更好 - 你总是可以有一个帮助类:

public static class BuilderInclusionsForm
{
    public static BuilderInclusionsForm<T> Create<T>(T product) where T : Product
    {
        return new BuilderInclusionsForm<T>(product);
    }
}

允许您使用类型推断。

答案 1 :(得分:3)

感谢Skeet先生,我的团队中一位聪明的成员指出了以下解决方案。

public BuilderInclusionsForm(Product p) : this()
{
    IEnumerable<Product> ps = db2.GetTable(p.GetType()).Cast<Product>();
    product = ps.SingleOrDefault(a => a.ProductID == p.ProductID);
}

抱歉浪费你的时间。请不要垃圾收集我的抱歉屁股约翰。 = OD