问题
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