2014-02-25 87 views
2

我想注入不同的字符串到我的每個模塊的構造函數。我註冊了構建模塊的工廠方法。然後我可以打電話container.Resolve<T>(),一切都很好。出於某種原因,儘管當南希試圖解決我的模塊,它拋出的錯誤註冊特定模塊構造函數

Nancy.TinyIoc.TinyIoCResolutionException:無法解析類型: Plugin.HomeModule ---> Nancy.TinyIoc.TinyIoCResolutionException: 無法解析類型:System

public class HomeModule : NancyModule 
{ 
    public HomeModule(string text) 
    { 
    } 
} 

protected override void ConfigureApplicationContainer(TinyIoCContainer container) 
{ 
    base.ConfigureApplicationContainer(container); 
    container.Register<HomeModule>((ctr, param) => { return new HomeModule("text"); }); 
    HomeModule module = container.Resolve<HomeModule>(); 
} 

我自己也嘗試做了登記ConfigureRequestContainer()具有相同的結果。我試過container.Register<HomeModule>(new HomeModule("some text"));以及AsSingleton()。我可以使用container.Register<string>("text")註冊一個字符串類型的實現,但是這會將相同的字符串注入到所有模塊中。

如何註冊一個模塊構造函數以便Nancy可以解決?

回答

3

模塊通過INancyModuleCatalog,它通常由引導程序實現的獲得,你必須創建一個自定義的變化 - 如果你正在使用默認的引導程序,那麼這是當前實現:

https://github.com/NancyFx/Nancy/blob/master/src/Nancy/DefaultNancyBootstrapper.cs#L205

+0

由於'INancyModule GetModule(TinyIoCContainer容器,類型moduleType)'被密封意思的最佳方式爲我寫方法的自定義實現是從'NancyBootstrapperWithRequestContainerBase '直接導出? – Despertar

+1

只需創建您自己的目錄實現並將其註冊到ConfigureApplicationContainer中,我只是將該方法指向默認實現的一個示例,因爲它稍微複雜一點,因爲模塊已在請求容器中註冊,而不是主應用程序容器。 –

2

最好的方法是不要將原語傳遞給你的模塊,但我們要更豐富一些,或者工廠。該容器可以解決這些依賴關係。將簡單的字符串傳遞到模塊是其他地方出現問題的跡象,並暗示您的架構可能需要重新思考

+1

容器也可以解析字符串類型。當我需要的時候傳遞一個產生我想要的值的工廠或者一個更豐富的類型時是一個字符串是差的設計IMO。藉助依賴注入,課程應始終提出所需的內容。第二個也是更大的問題是IOC會將注入的類解析爲相同的值(不管註冊到哪個模塊),所有模塊都不允許將唯一值傳遞給作爲問題核心的模塊構造函數。 – Despertar

+1

我個人認爲它的好設計,沒有什麼比使用需要隨機字符串值的ctors項目工作更糟,這使得他們難以弄清楚他們爲或做的任何事情。 – Phill

+0

@Phill上面寫的代碼只是一個任意的例子,構造函數可以帶*任何*種類的值或類。我想展示一些簡單的東西來展示我想要做的事情。我是依賴注入的忠實粉絲,我希望避免在任何可能的情況下進入全局狀態以獲取對象所需的值。出於這個原因,我正在研究如何以每個模塊爲基礎自然地將數據傳遞給我的模塊。由於Nancy與IOC容器強大集成,我認爲註冊模塊工廠可以很容易地定製模塊的構建方式。 – Despertar

0

我實現了僅註冊特定命名空間的模塊的自定義目錄,但我不知道在哪裏註冊這個。

public CustomModuleCatalog() 
{ 
    // The license type is read from db in Global.ascx. 
    // So I want to register a module based on a namespace. 
    // The namespace is the same like the license name. 
    if(WebApiApplication.LicenseType == LicenseType.RouteOne) 
    { 
     var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes(); 
     var modules = assemblyTypes.Where(t => t.Namespace != null && t.Namespace.EndsWith("MyCustomNamespace")); 
     var nancy = modules.Where(t => t.IsAssignableFrom(typeof(INancyModule))); 
     foreach (var type in nancy) 
     { 
      var nancyType = (INancyModule)type; 
      _modules.Add(type, (INancyModule)Activator.CreateInstance(type)); 
     } 
    } 
} 

public IEnumerable<INancyModule> GetAllModules(NancyContext context) 
{ 
    return _modules?.Values; 
} 

public INancyModule GetModule(Type moduleType, NancyContext context) 
{ 
    if (_modules != null && _modules.ContainsKey(moduleType)) 
    { 
     return _modules[moduleType]; 
    } 
    return null; 
}