C #: определить тип производного объекта из статического метода базового класса
-
08-07-2019 - |
Вопрос
В программе на C # у меня есть абстрактный базовый класс со статическим тегом " Создать " метод. Метод Create используется для создания экземпляра класса и его локального хранения для последующего использования. Поскольку базовый класс абстрактный, объекты реализации всегда будут производными от него.
Я хочу иметь возможность извлечь объект из базового класса, вызвать статический метод Create (реализованный один раз в базовом классе) через производный класс и создать экземпляр производного объекта.
Существуют ли какие-либо средства на языке C #, которые позволят мне это осуществить. Моя текущая резервная позиция - передать экземпляр производного класса в качестве одного из аргументов функции Create, т.е.
objDerived.Create(new objDerived(), "Arg1", "Arg2");
Решение
Попробуйте использовать дженерики.
public static BaseClass Create<T>() where T : BaseClass, new()
{
T newVar = new T();
// Do something with newVar
return T;
}
Пример использования:
DerivedClass d = BaseClass.Create<DerivedClass>();
Другие советы
Резюме
Есть два основных варианта. Лучше и новее использовать дженерики, а другое - рефлексию. Я предоставляю оба варианта на тот случай, если вам понадобится разработать решение, работающее до .NET 2.0.
Дженерики
abstract class BaseClass
{
public static BaseClass Create<T>() where T : BaseClass, new()
{
return new T();
}
}
Где будет использование:
DerivedClass derivedInstance = BaseClass.Create<DerivedClass>();
Отражение
abstract class BaseClass
{
public static BaseClass Create(Type derivedType)
{
// Cast will throw at runtime if the created class
// doesn't derive from BaseClass.
return (BaseClass)Activator.CreateInstance(derivedType);
}
}
Где будет использование (разбить на две строки для удобства чтения):
DerivedClass derivedClass
= (DerivedClass)BaseClass.Create(typeof(DerivedClass));
Вы хотите создать новый экземпляр производного из другого экземпляра производного, используя метод статической фабрики в абстрактном базовом классе? если это так, мне интересно, почему ... Но ...
public abstract class MyBase
{
public static T GetNewDerived<T>() where T : MyBase, new()
{
return new T();
}
}
public class DerivedA : MyBase
{
public static DerivedA GetNewDerived()
{
return GetNewDerived<DerivedA>();
}
}
public class DerivedB : MyBase
{
public static DerivedB GetNewDerived()
{
return GetNewDerived<DerivedB>();
}
}
Это то, что вы хотите?
Похоже, вам нужно сделать метод Create () абстрактным. И как только вы это сделаете, вы можете также переименовать его и сделать его конструктором. Тогда у вас может быть другой метод Init (), который вы вызываете после создания объекта, если вам нужно, и обычные эффекты полиморфизма будут обрабатывать вещи.
Вы не можете сделать это без посторонней информации; либо тип производного класса, его экземпляр, либо полное имя производного класса. Любое из них эквивалентно тому, что вы уже делаете; нет лучшего решения, о котором я знаю. Сама природа статических методов исключает что-либо более элегантное.
Я не уверен, каковы ваши цели дизайна, но из того, что вы спросили, звучит так, как будто это может закончиться с большим количеством запаха кода. Я думаю, что вы действительно должны изучить шаблоны проектирования Inversion of Control (IoC) / Dependency Injection (DI), которые реализованы в многочисленных средах, таких как Microsoft Unity, Castle Windsor, StructureMap, Ninject, Spring.Net и т. Д.
Я думаю, что если вы посмотрите на использование контейнера IoC, это решит вашу проблему намного чище и слабо связанно.