2013-09-24 3 views
-1

Я хотел бы знать, есть ли способ иметь диспетчер ClassClass, который вызывает конструкторы разных классов, которые используют один и тот же интерфейс и наследуют форму того же базового класса. Я не могу сам вызвать конструкторы определенных производных классов, потому что пользователь может выбирать, какие объекты создавать во время выполнения, поэтому я не знаю, какие производные объекты создаются до выполнения.Вызов конструкторов разных классов, которые реализуют один и тот же интерфейс и выводятся из одной базы?

Например:

public class managerClass : ISomeInterface 
{ 
    public BaseClass apply(someDataType) //(Notice return type is BaseClass) 
    { 

пробега конструкторов derivedClasses или создавать принципиально новые производные объекты, проходит someDataType в конструкторы

} 
} 

public class derivedClass : BaseClass, ISomeInterface 
{ 
    public void doSmthg(){manipulate data and store} 
} 
public class derivedClass2 : BaseClass, ISomeInterface 
{ 
    public void doSmthg(){manipulate data in another way and store} 
} 

В настоящее время managerClass не наследующих тот же BaseClass, если это как-то помогает мне делать то, что я хочу делать, я не ага внесите это изменение.

+0

вы хотите, чтобы ваш класс менеджер для создания экземпляров различных конкретных классов, в зависимости от пользовательского ввода? –

+0

Да, это возможно? – user1084113

+0

Посмотрите шаблон абстрактного завода и посмотрите, подходит ли это вашему прецеденту. –

ответ

0

Вы можете взглянуть на Activator класс:

Type type = typeof(derivedClass2); 
ISomeInterface instance = (ISomeInterface)Activator.Create(type); 

Есть еще несколько перегруженных, как проплывающие имя класса вместо типа.

Подробнее: http://msdn.microsoft.com/en-us/library/system.activator.aspx

Else вы должны смотреть на Factory Design Pattern здесь http://msdn.microsoft.com/en-us/library/ee817667.aspx

0

В чем проблема? Конечно, вы можете сказать:

public BaseClass Apply(SomeDataType someDataType) 
{ 
    BaseClass instance; 
    if (/* your condition */) 
    { 
    var dc = new DerivedClass(); 
    // do stuff to/with dc 
    instance = dc; 
    } 
    else 
    { 
    var dc2 = new DerivedClass2(); 
    // do stuff to/with dc2 
    instance = dc2; 
    } 
    // do common stuff to/with instance 
    return instance; 
} 
+0

Я бы не хотел этого делать, потому что тогда дизайн не расширяется, если разработчик должен был создать другой производный класс, они также должны были бы добавить это условие if.В настоящее время ManagerClass хранит все объекты, реализующие ISomeInterface, и вызывает их методы doSmthg, поэтому, если разработчик должен создать другой производный класс, им нужно реализовать этот метод и наследовать от BaseClass. – user1084113

+1

Что вы предпочитаете? Является ли пользователь просто передачей имени создаваемой реализации? –

+1

@ user1084113 Вы должны отредактировать свой вопрос, чтобы включить информацию о том, что существуют многие производные классы, и, возможно, позже потребуется добавить их. Также вы должны написать что-то о том, как он должен определяться _which_ производным классом для использования в каждом конкретном случае. Возможно, я неправильно понял ваш вопрос, имея дело с «производными классами» и «производным классом2». –

0

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

Dictionary<string, Type> DerivedOfferings{get;set;} 

... //somewhere in the setup of your manager. 

foreach (Type t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IEmtRequestProcessor))))) 
{ 
    DerivedOfferings.Add(t.Name, t); 
} 

//provide list of options to users. 
IList<string> GetOfferingOptions(){ 
    return DerivedOfferings.Keys.ToList(); 
} 

... 

public BaseClass GetOffering(string name){ 
    return (BaseClass)Activator.CreateInstance(DerivedOfferings[type]); 
} 

Если есть какая-то логика, которая должна быть выполнена, чтобы решить, какие производном предлагает создать, вы можете использовать атрибут для разработчиков, чтобы украсить свои классы, которые будут содержать информацию для выполнения логики против.

public sealed class CreatureAttribute:Attribute 
{ 
    public int NumberOfLegs{get;set;} 
    public Color HairColor{get;set;} 
    public int NumberOfWings{get;set;} 
    public bool BreathsFire{get;set;} 
} 

[CreatureAttribute(NumberOfLegs=6, HairColor = Color.Magenta, NumberOfWings=0, BreathsFire=True)] 
public class PurpleDragon: ICreature 
{ 
... 
} 

Затем загрузите их во время перечисления и сохраните их с опциями.

List<CreatureCriteria> CreatureOptions{get;set;} 
EnumerateOptions() 
{ 
    foreach (Type t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICreature))))) 
    { 
     foreach (CreatureAttribute creatureAttribute in 
       t.GetCustomAttributes(typeof (CreatureAttribute), false) 
       .Cast<CreatureAttribute>()      
      { 
       CreatureOptions.Add(
        new CreatureCriteria{ 
          Legs = creatureAttribute.NumberOfLegs, 
          HairColor = creatureAttribute.HairColor, 
          ... 
          ConcreteType = t 
        } 
       ); 
      } 
    } 
} 

и оценки на основе критериев, предоставленных пользователем ..

ICreature CreateCreature(CreatureCriteria criteria){ 
    CreatureCriteria bestMatch = CreatureOptions.FindBestMatch(criteria); 
    // perform logic comparing provided criteria against CreatureOptions to find best match. 
    return (ICreature)Activator.CreateInstance(bestMatch.ConcreteType); 
} 
Смежные вопросы