调用实现相同接口并从同一Base派生的不同类的构造函数?

时间:2013-09-24 14:29:47

标签: c# class inheritance design-patterns interface

我想知道是否有办法让一个ManagerClass调用不同类的构造函数,这些构造函数共享相同的接口并从相同的基类继承。我无法调用特定的派生类构造函数本身,因为用户可以选择在运行时创建哪些对象,因此我不知道在运行时要创建哪些派生对象。

例如:

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继承,但是如果这有助于我做我想做的事情,我并不反对做出这样的改变。

3 个答案:

答案 0 :(得分:0)

您可以查看Activator课程:

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

还有一些重载,比如传递类名而不是类型。

更多信息:http://msdn.microsoft.com/en-us/library/system.activator.aspx

否则,您应该Factory Design Pattern http://msdn.microsoft.com/en-us/library/ee817667.aspx

查看{{1}}

答案 1 :(得分: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;
}

答案 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);
}