3

好的,所以我有一个名为 Product 的抽象类。我有 3 个表,分别称为 Items、Kits 和 Packages,它们实现了 Product。Product 具有公开对象主键的公共属性。

那就是说我有一个传递产品的表格。我想将该产品从一个新的数据上下文中拉出来,而不必编写一个反映它的类型的大开关来获得它的正确表。

我想做这样的事情,但演员表不接受 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);   
4

2 回答 2

5

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

您可以在产品类型中使 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);
    }
}

这将允许您使用类型推断。

于 2009-01-13T14:24:06.427 回答
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

于 2009-02-27T12:52:23.277 回答