Get an entity from a table using reflection from an abstract type

Ok, so I have an abstract class called Product. I have 3 tables called “Items, Sets, and Packages” that implement the product. The product has a public property that provides the primary key of the object.

I have a form where I transfer the product. I would like to pull this product from a new data file without having to write a large switch reflecting its type in order to get its proper table.

I wanted to do something like this, but bit-bit will not 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 that:

 public BuilderInclusionsForm(Product p) : this() { Type foo = p.GetType(); product = db2.GetTable(p.GetType()).OfType<foo>().SingleOrDefault(a => a.ProductID == p.ProductID); 
+3
c # linq abstraction
source share
2 answers

Thanks to Mr. Skeet, a vibrant member of my team pointed to 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 rubbish pick up my miserable ass of John. = O.D.

+3
source share

No, because the type argument must be known at compile time so that it appears in the source code.

You can either make BuilderInclusionsForm generic in the product type, 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 call 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 can cache the open form of the method.)

Not bad, but it should work. I suspect that it would be best to create a BuilderInclusionsForm, but you can 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 allows you to use type inference.

+5
source share

All Articles