我有一个带有生成派生类的静态工厂方法的基类:
public class Fruit
{
...
static Dictionary<string, Type> classes = new Dictionary<string, Type>
{
{"apple", typeof(Apple)}
,{"orange", typeof(Orange)}
}
public static Fruit makeFruit(string typeName) {
if(classes[typeName] == null) throw new Exception("invalid fruit type");
Fruit fruit = Activator.CreateInstance(classes[typeName]) as Fruit;
// do some intializations
return fruit;
}
}
如何在不修改 Fruit 类代码本身的情况下添加从 Fruit 派生的类并让 Fruit 类知道它?实际上,我需要能够简单地通过放入 Banana.DLL 或将 Banana.cs 文件添加到我的项目中来添加水果。在 javascript 等其他语言中,我只需在类声明之后将类添加到 Fruit 的静态数组:
function Banana()
{
...
}
Fruit.classes['banana'] = Banana;
当然这在 C# 中是不可能的,我尝试将代码放在静态构造函数中,但这也不起作用,因为 ctor 仅在类的第一次实例化之前被调用。想到的另一种解决方法是让基类扫描所有程序集中定义的所有类以查找其所有派生类并从每个派生类中定义的静态字符串成员中检索 typeName 但这感觉有点过头了。你有什么建议?
以下是 Gupta 建议使用 MEF 之后我现在正在做的事情:
添加了一个这样的水果信息类:
abstract class FruitInfo
{
readonly Type type;
readonly string typeName;
public FruitInfo(Type type, string typeName)
{
this.type = type;
this.typeName = typeName;
}
}
为每个 Fruit 创建一个 FruitInfo 类:
class Banana : Fruit
{
...
}
[Export(typeof(FruitInfo))]
class BananaInfo : FruitInfo
{
public BananaInfo() : base(typeof(Banana), "banana") { }
};
在 Fruit 中使用这个静态函数来导入类型:
public static void importAllFruitTypes()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
IEnumerable<FruitInfo> fruitInfos = container.GetExportedValues<FruitInfo>();
foreach(FruitInfo fruitInfo in fruitInfos) {
class[fruitInfo.typename] = fruitInfo.type;
}
}
任何改进这一点的建议仍然非常受欢迎。