2012-03-07 64 views
3

我的項目已經包含了一些處理程序的工廠(代碼非常簡單):處理程序工廠的依賴注入設計

class HandlersFactory 
{ 
    private static readonly Dictionary<string, IHandler> registeredHandlers = 
     new Dictionary<string, IHandler> 
     { 
      { "First", new FirstHandler() }, 
      { "Second", new SecondHandler() }, 
      { "Third", new ThirdHandler() }, 
     }; 

    public bool IsRegisteredHandler(string name) 
    { 
     return registeredHandlers.ContainsKey(name); 
    } 

    public IHandler GetHandler(string name) 
    { 
     if (!IsRegisteredHandler(name)) 
      return null; 

     return registeredHandlers[name]; 
    } 
} 

處理程序的列表是硬編碼。 Factory位於主程序集中,但應用程序可以在運行時通過附加程序集進行擴展(主應用程序搜索它們並在開始時加載)。其他裝配自定義應用

必須有一種可能性,用新組件替換主組件中的一些處理程序(提供另一種邏輯)。因此,例如,當加載額外的組件時,工廠將按名稱「Second」返回CustomSecondHandler而不是SecondHandler。我可以重寫工廠,但更改不得影響已經使用它的代碼。

我想過將字典初始化移動到某些方法RegisterHandlers,可以在自定義工廠中覆蓋。並添加工廠的依賴注入,因此額外的程序集提供了從現有工廠派生的工廠自己的實現。如果沒有加載額外的組件,則使用默認工廠。但我覺得這種方法有問題。

請提出你的想法。我需要一個乾淨的解決方案,用最少的代碼編寫代碼來提供將替換現有處理程序的定製處理程序

謝謝。

回答

5

你如何掃描你的程序集?如果你使用反射,你可以利用custom attributes。試想一下:

[ForcesHandlerRegistrationOverride] 
public class CustomSecondHandler : IHandler 
{ 
    // ... 
} 

我假設你有辦法來生成負載處理正確的字典鍵,以及建立處理程序實例 - 跳過那些部分(namehandler變量初始化),這裏的組裝掃描可能什麼樣子:

var types = loadedAssembly 
    .GetTypes() 
    .Where(t => type.IsAssignableFrom(typeof(IHandler))); 

foreach (var type in types) 
{ 
    if (factory.IsRegisteredHandler(name)) 
    { 
     // usually you'll do nothing here, but now we check if handler 
     // we want to register is marked with custom attribute so that 
     // we can override already registered handler 
     var canForceOverride = type.GetCustomAttributes(
      typeof(ForcesHandlerRegistrationOverride), true).Length > 0; 
     if (canForceOverride) 
     { 
      factory.RegisterHandler(name, handler); 
      // ...or to keep this one safe, add more appropriate method 
      // for explicit replacement (see note below) 
     }  
    } 
    else 
    { 
     factory.RegisterHandler(name, handler); 
    } 
} 

如果你的工廠類的註冊方法在某種程度上對守衛處理程序添加到已經存在的鍵兩次,你可能必須擺脫的那個(或暴露的註冊方法,可以取代處理;像ReplaceHandlerForceRegistration)。

這將讓您輕鬆控制何時應該覆蓋/替換現有的處理程序,或者只需註冊爲新的處理程序。

請注意,您甚至可以將其更進一步;用它應該替換的處理程序名稱聲明屬性 - [ForcesHandlerRegistrationOverride("Second")]

+0

一個絕妙的主意!和一個非常乾淨的解決方案我可能會從字典中刪除'readonly',並添加掃描定製處理程序的附加程序集的方法。謝謝! – 2012-03-07 23:26:32