2012-07-25 79 views
0

我有一个基类的静态工厂方法,使派生类:地图类型名称派生类

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; 
    } 
} 

如何添加从果派生的类,让水果类了解它,而无需修改水果类代码本身?其实我只需要通过放入Banana.DLL或添加Banana.cs文件到我的项目中即可添加水果。在像JavaScript等语言我只需添加类水果的静态数组类声明之后:

function Banana() 
{ 
    ... 
} 
Fruit.classes['banana'] = Banana; 

当然这是不可能在C#中,我试图把代码中的静态构造函数内部,但也不至于工作要么是因为ctor只在类的第一个实例化之前被调用。想到的另一个解决方法是让基类扫描所有程序集中定义的所有类,以找到其所有派生类,并从每个派生类中定义的静态字符串成员中检索typeName,但感觉像是矫枉过正。你有什么建议?


下面是我在做什么,现在古普塔的建议后使用MEF:

加了水果的信息类这样的:

abstract class FruitInfo 
{ 
    readonly Type type; 
    readonly string typeName; 

    public FruitInfo(Type type, string typeName) 
    { 
     this.type = type; 
     this.typeName = typeName; 
    } 
} 

创建每个水果一个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; 
    } 
} 

任何改善此问题的建议仍然非常受欢迎。

+1

如果我理解正确的话,那么你应该检查MEF(托管扩展框架),检查此链接http://msdn.microsoft.com/en-us/library/dd460648.aspx – 2012-07-25 11:15:20

+0

感谢Gupta,MEF似乎是要走的路,发布它作为答案,以便我可以接受它。 – nobody 2012-07-26 07:57:05

回答

2

你必须寻找继承水果的类,但你不能到处看。您需要定义您想要查看的程序集。如果所有的类都是在相同的组件,然后很容易:

var types = Assembly.GetAssembly(tyepof(Fruit)).GetTypes(); 
var derived = types.Where(t => t.IsSubclassOf(typeof(Fruit)).Select(t => new { t.Name, t }); 
+0

+1为'IsSubclassOf' – Ria 2012-07-25 11:33:30

+0

我提到我已经知道这种方法,我试图避免它。 – nobody 2012-07-26 07:58:21