2012-07-25 70 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