我有一個基類的靜態工廠方法,使派生類:地圖類型名稱派生類
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;
}
}
任何改善此問題的建議仍然非常受歡迎。
如果我理解正確的話,那麼你應該檢查MEF(託管擴展框架),檢查此鏈接http://msdn.microsoft.com/en-us/library/dd460648.aspx – 2012-07-25 11:15:20
感謝Gupta,MEF似乎是要走的路,發佈它作爲答案,以便我可以接受它。 – nobody 2012-07-26 07:57:05