абстрагирование класса - PullRequest
       1

абстрагирование класса

4 голосов
/ 20 декабря 2011

У меня есть базовый абстрактный класс с несколькими классами, которые расширяют и переопределяют его, однако все они имеют один и тот же конструктор.Прямо сейчас я вызываю каждый конструктор из оператора switch:

case 1: return new A(arg1); // arg is int

и т. Д. Примерно для 10 классов.Есть ли способ с обобщениями или делегатами создать один метод, который бы взял имя класса и создавал экземпляр этого типа с аргументами?

Это помогло бы, поскольку, если я внесу изменение в конструкторы, мне также придется изменить каждыйinstantiation.

Делегат был бы наиболее простым, но исследования говорят «нет» назначению конструкторов делегатам.

ДОПОЛНЕНИЕ: я сейчас на Wi-Fi со своим ноутбуком, а не только с моей камерой, поэтому здесьприходит некоторый код.

Это пример того, что происходит сейчас:

switch (new Random().Next(4))
{
    case 3:
         // classA : baseClass, args{int, bool, otherClass}
         return new classA(arg1, arg2, arg3);
    case 2:
         // classB : baseClass, args{int, bool, otherClass}
         return new classB(arg1, arg2, arg3);
    case 1:
         // classC : baseClass, args{int, bool, otherClass}
         return new classC(arg1, arg2, arg3);
    case 0:
         // classD : baseClass, args{int, bool, otherClass}
         return new classD(arg1, arg2, arg3);
    default:
         continue;
}

Я хотел бы вызвать один экземпляр в конце блока с тремя аргументами.

Решение, о котором я подумал, состоит в создании класса-экземпляра, который работает примерно так:

ClassInstantiator inst = new ClassInstantiator(arg1, arg2, arg3);
switch(new Random().Next(4))
{
     case 4:
         return inst.instantiate<classA>();
     ...
}

Это уже встроено в язык, или кто-нибудь знает о более элегантном решении?

Ответы [ 4 ]

5 голосов
/ 20 декабря 2011

Единственное связанное с конструктором ограничение, которое вы можете наложить на универсальный тип, - это ограничение new(), для которого требуется открытый конструктор без параметров.

Вы можете использовать отражение; В примере предполагается, что все связанные типы имеют конструктор, принимающий int, как в вашем примере, и что абстрактный базовый класс называется B:

public T CreateInstance<T>(int i) where T : B
{
    return (T)Activator.CreateInstance(typeof(T), i);
}

Тогда вы бы назвали это так:

A a = CreateInstance<A>(3);
5 голосов
/ 20 декабря 2011

Вы не можете уйти от того факта, что что-то должно решаться на условной основе, что строить, но вы можете инкапсулировать это.Могу я представить вам один из самых популярных паттернов GOF: http://en.wikipedia.org/wiki/Factory_method_pattern

например

public abstract class MyBase(string name){}
public class Concrete1 : MyBase{}
public class Concrete2 : MyBase{}

public class MyFactory
{
   public MyBase Create(Criteria criteria)
   {
       //conditional logic/reflection
   }
}
1 голос
/ 21 декабря 2011

Вы можете создать словарь с именем класса в качестве ключа и делегатом конструктора в качестве значения.

Dictionary<string,Func<int,BaseClass>> _dict = new Dictionary<string,Func<int,BaseClass>>();
_dict.Add("ClassA", i => new ClassA(i));
_dict.Add("ClassB", i => new ClassB(i));

// Create ClassA object by class name
BaseClass obj = _dict["ClassA"](5);
0 голосов
/ 20 декабря 2011

Я не хочу чрезмерно усложнять вашу проблему, но если вы обнаружите, что у вас много такого кода, то вам может быть интересно использовать контейнер IoC.

Популярные контейнеры IoC:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...