Get Entity From Table Using Reflection From Abstract Type

非 Y 不嫁゛ 提交于 2019-12-10 19:24:53

问题


Ok, so I have an abstract class called Product. I have 3 tables called Items, Kits, and Packages that implement Product. Product has a public property that exposes the object's primary key.

That said I have a form where I pass a product. I would would like to pull that product out of a fresh datacontext without having to write a big switch reflecting it's type to get its proper table.

I wanted to do something like this but the cast bit won't accept foo.

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

or this:

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

回答1:


No, because the type argument has to be known at compile-time to appear in source code.

You could either make BuilderInclusionsForm generic in the type of product, or write a generic method like this:

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

and then invoke it with reflection:

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 });
}

(Obviously you could cache the open form of the method.)

Not nice, but it should work. I suspect it would be nicer to just make BuilderInclusionsForm generic though - you could always have a helper class:

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

which would allow you to use type inference.




回答2:


With thanks to Mr. Skeet a bright member of my team pointed out the following solution.

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

Sorry to waste your time. Please don't garbage collect my sorry ass John. =oD



来源:https://stackoverflow.com/questions/439086/get-entity-from-table-using-reflection-from-abstract-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!