Получить сущность из таблицы, используя отражение от абстрактного типа
-
22-07-2019 - |
Вопрос
Хорошо, у меня есть абстрактный класс с именем Product. У меня есть 3 таблицы, которые называются Предметы, Комплекты и Пакеты, которые реализуют Продукт. Продукт имеет открытое свойство, которое предоставляет первичный ключ объекта.
Тем не менее, у меня есть форма, в которой я передаю товар. Я хотел бы вытащить этот продукт из нового текста данных без необходимости написания большого переключателя, отражающего его тип, чтобы получить правильную таблицу.
Я хотел сделать что-то подобное, но приёмник не принимает 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
Благодаря господину Скиту яркий член моей команды указал на следующее решение.
public BuilderInclusionsForm(Product p) : this()
{
IEnumerable<Product> ps = db2.GetTable(p.GetType()).Cast<Product>();
product = ps.SingleOrDefault(a => a.ProductID == p.ProductID);
}
Извините, что потратил ваше время. Пожалуйста, не собирай мусор, моя жалкая задница, Джон. = О.Д. р>
Другие советы
Нет, потому что аргумент типа должен быть известен во время компиляции, чтобы появиться в исходном коде.
Вы можете либо сделать BuilderInclusionForm универсальным в типе продукта, либо написать общий метод, подобный этому:
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 });
}
(Очевидно, вы можете кэшировать открытую форму метода.)
Не красиво, но должно работать. Я подозреваю, что было бы лучше просто сделать BuilderInclusionForm универсальным, хотя - у вас всегда мог быть вспомогательный класс:
public static class BuilderInclusionsForm
{
public static BuilderInclusionsForm<T> Create<T>(T product) where T : Product
{
return new BuilderInclusionsForm<T>(product);
}
}
который позволил бы вам использовать вывод типа.