C #: определить тип производного объекта из статического метода базового класса

StackOverflow https://stackoverflow.com/questions/300181

Вопрос

В программе на 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, это решит вашу проблему намного чище и слабо связанно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top