根据值决定创建哪个派生 Class?
Deciding Which Derived Class To Create Based On A Value?
我想知道这是否可能。我有许多 classes,它们都来自相同的基数 class (BaseClass
)。当我创建实例时,我需要根据配置值决定我需要创建哪个派生 class。目前我正在做下面的事情,但我希望有一种更简洁的方法来实现它,如果我需要添加一个新的派生 class.
,那将需要更少的维护
BaseClass myclass;
switch (Config.ClassToUse)
{
case 1:
myclass= new DerivedClass1(Config);
break;
case 2:
myclass= new DerivedClass2(Config);
break;
case 3:
myclass = new DerivedClass3(Config);
break;
}
myclass.DoWork();
DoWork
方法中的代码 因 class 的每个不同实例而异。
希望这是有道理的。
具有 Config.ClassToUse return 派生类型 class 而不是标识它的整数。
那么你的代码可以缩短为:
BaseClass myclass = System.Activator.CreateInstance(Config.ClassToUse)
知道要创建哪个class,这就是让我们Config
完成它的工作的原因。我们应该去掉 幻数(2
代表什么?)和 return Type
,而不是 int
.
快速补丁是
public class Config {
...
// Get rid of this, move logic into TypeToUse
public int ClassToUse {get { ... }}
public Type TypeToUse {
get {
string name = $"DerivedClass{ClassToUse}";
// Here we scan all types in order to find out the best one. Class must be
// 1. Derived from BaseClass
// 2. Not Abstract (we want to create an instance)
// Among these classes we find the required by its name DerivedClass[1..3]
// (as a patch). You should implement a more elaborated filter
// If we have several candidates we'll take the 1st one
return AppDomain
.CurrentDomain
.GetAssemblies() // scan all assemblies
.SelectMany(asm => asm
.GetTypes() // and all types
.Where(tp => typeof(BaseClass).IsAssignableFrom(tp))) // ... for derived classes
.Where(tp => !tp.IsAbstract) //TODO: Add more filters if required
.Where(tp => tp.Name.Equals(name)) //TODO: put relevant filter here
.FirstOrDefault();
}
}
public BaseClass CreateInstance() {
Type tp = TypeToUse;
if (tp == null)
return null; // Or throw exception
return Activator.CreateInstance(tp, this) as BaseType;
}
}
那你可以把
BaseClass myclass = Config.CreateInstance();
myclass.DoWork();
我想知道这是否可能。我有许多 classes,它们都来自相同的基数 class (BaseClass
)。当我创建实例时,我需要根据配置值决定我需要创建哪个派生 class。目前我正在做下面的事情,但我希望有一种更简洁的方法来实现它,如果我需要添加一个新的派生 class.
BaseClass myclass;
switch (Config.ClassToUse)
{
case 1:
myclass= new DerivedClass1(Config);
break;
case 2:
myclass= new DerivedClass2(Config);
break;
case 3:
myclass = new DerivedClass3(Config);
break;
}
myclass.DoWork();
DoWork
方法中的代码 因 class 的每个不同实例而异。
希望这是有道理的。
具有 Config.ClassToUse return 派生类型 class 而不是标识它的整数。
那么你的代码可以缩短为:
BaseClass myclass = System.Activator.CreateInstance(Config.ClassToUse)
知道要创建哪个class,这就是让我们Config
完成它的工作的原因。我们应该去掉 幻数(2
代表什么?)和 return Type
,而不是 int
.
快速补丁是
public class Config {
...
// Get rid of this, move logic into TypeToUse
public int ClassToUse {get { ... }}
public Type TypeToUse {
get {
string name = $"DerivedClass{ClassToUse}";
// Here we scan all types in order to find out the best one. Class must be
// 1. Derived from BaseClass
// 2. Not Abstract (we want to create an instance)
// Among these classes we find the required by its name DerivedClass[1..3]
// (as a patch). You should implement a more elaborated filter
// If we have several candidates we'll take the 1st one
return AppDomain
.CurrentDomain
.GetAssemblies() // scan all assemblies
.SelectMany(asm => asm
.GetTypes() // and all types
.Where(tp => typeof(BaseClass).IsAssignableFrom(tp))) // ... for derived classes
.Where(tp => !tp.IsAbstract) //TODO: Add more filters if required
.Where(tp => tp.Name.Equals(name)) //TODO: put relevant filter here
.FirstOrDefault();
}
}
public BaseClass CreateInstance() {
Type tp = TypeToUse;
if (tp == null)
return null; // Or throw exception
return Activator.CreateInstance(tp, this) as BaseType;
}
}
那你可以把
BaseClass myclass = Config.CreateInstance();
myclass.DoWork();