2012-04-26 54 views
0

我在我的Ninject模塊中重複了幾次以下的代碼。我可以使用哪些方法和技術來減少這些重複的代碼?請求IDirectoryBuilder,其主要功能是確定通過使用IDirectory實施的基礎上配置設置的文件的位置時發生如何讓我的Ninject模塊乾燥?

public override void Load() 
{ 
    Bind<IDataReader<IList<Price>>>() 
     .To<PricesDataReader>().Named("ValDatePrices"); 
    Bind<IDataConnection<IList<PricesCsvRecord>>>() 
     .To<PricesXLConnection>().WhenParentNamed("ValDatePrices") 
     .Named("ValDatePricesXLConnection"); 
    Bind<IDirectoryBuilder>() 
     .ToMethod(DefaultValDatePricesDirectory) 
     .WhenParentNamed("ValDatePricesXLConnection"); 

    Bind<IDataReader<IList<Price>>>() 
     .To<PricesDataReader>().Named("EDDatePrices"); 
    Bind<IDataConnection<IList<PricesCsvRecord>>>() 
     .To<PricesXLConnection>().WhenParentNamed("EDDatePrices") 
     .Named("EDDatePricesXLConnection"); 
    Bind<IDirectoryBuilder>() 
     .ToMethod(DefaultEDDatePricesDirectory) 
     .WhenParentNamed("EDDatePricesXLConnection"); 
} 

的主要區別。

在上面的例子中,我返回一個DefaultDirectoryBuilder,但是我有幾個其他的實現(請參閱下面的EdNrrDirectoryBuilder方法)。

public IDirectoryBuilder DefaultValDatePricesDirectory(IContext arg) 
{ 
    return new DefaultDirectoryBuilder(
     ConfigurationManager.AppSettings["VALDATE_PRICES_DIR"], 
     ConfigurationManager.AppSettings["VALDATE_PRICES_FILENAME"]); 
} 

public IDirectoryBuilder DefaultEDDatePricesDirectory(IContext arg) 
{ 
    return new DefaultDirectoryBuilder(
     ConfigurationManager.AppSettings["EDDATE_PRICES_DIR"], 
     ConfigurationManager.AppSettings["EDDATE_PRICES_FILENAME"]); 
} 

public IDirectoryBuilder EdNrrDirectoryBuilder(IContext arg) 
{ 
    return new ExternalDirectoryBuilder(
     ValuationDate, 
     ConfigurationManager.AppSettings["NRRDATE_DIR"], 
     ConfigurationManager.AppSettings["NRRDATE_PRICES_FILENAME"]); 
} 

我的問題是我需要我的配置文件的值。現在,所有與配置相關的請求在我的Ninject模塊中都是有限的。

如果我使用Ninject工廠方法創建IDirectoryBuilder s,我看到的方式是我需要將ConfigurationManager相關的調用分散在我的代碼庫中。

如果我使用Ninject Provider方法,我將需要所有實現IDirectoryBuilder的提供者,並且還更新了我的構造函數和IDataConnection的實現。我的代碼現在看起來像(不是非常乾燥,類似於我目前的方法)。

Bind<IDirectoryBuilder>().ToProvider<DefaultDirectoryBuilderProvider>() 
    .WhenParentNamed("EDDatePricesXLConnection") 
    .WithConstructorArgument("baseDir", "someConfigValue") 
    .WithConstructorArgument("fileName", "someOtherConfigValue"); 

我的代碼具有目前一個非常一致的依賴鏈(使用NamedArguments):ICalculator - >IDataReader - >IDataConnection - >IDirectoryBuilder - 這使我相信,必須有某種方式來重複創建這條產業鏈而不必重複設置代碼 - 我似乎無法弄清楚。還有一個額外的限制,因爲我經常需要兩個相同的依賴鏈實例 - 唯一的區別是配置值不同。

+0

參見http://stackoverflow.com/questions/10344568/binding-recurring-connection-string-constructor-parameters-using-di – 2012-04-27 07:36:41

回答

0

基於魯本的評論,這是我目前的解決方案。我做的一個細節是使用約定的概念,因此檢索我的配置設置變得更容易。這通過使用Ninject Named參數的大多數其他代碼進行過濾。

public void Load(){ 
    BindDependencies<IDataReader<IList<Price>>, PricesDataReader 
     , IDataConnection<IList<PricesCsvRecord>>, PricesXLConnection 
     , DefaultDirectoryBuilder> 
     ("ValDatePrices"); 

    BindDependencies<IDataReader<IList<Price>>, PricesDataReader 
     , IDataConnection<IList<PricesCsvRecord>>, PricesXLConnection 
     , DefaultDirectoryBuilder> 
     ("EDDatePrices"); 
     // etc etc 
} 

public void BindDependencies< 
    TReaderBase, TReaderImpl, 
    TDataConnectionBase, TDataConnectionImpl, 
    TDirectoryBuilderFactoryImpl> 
    (string baseName) 
     where TReaderImpl : TReaderBase 
     where TDataConnectionImpl : TDataConnectionBase 
{ 
    DirectoryBuilderInfo dirInfor = GetSettings(baseName); 

    Bind<TReaderBase>() 
      .To(typeof(TReaderImpl)) 
      .Named(baseName); 
    Bind<TDataConnectionBase>().To(typeof(TDataConnectionImpl)) 
      .WhenParentNamed(baseName) 
      .Named(baseName + "XLConnection"); 
    Func<IDirectoryBuilder> directoryBuilder = CreateDirectoryBuilderFunc<TDirectoryBuilderFactoryImpl>(dirInfor); 

    Bind<IDirectoryBuilder>() 
      .ToMethod(d => directoryBuilder()) 
      .WhenParentNamed(baseName + "XLConnection"); 
    } 

private Func<IDirectoryBuilder> CreateDirectoryBuilderFunc<TDirectoryBuilderFactoryImpl>(DirectoryBuilderInfo dirInfor) 
{ 
    Func<IDirectoryBuilder> directoryBuilder = 
     () => CreateDefaultDirectoryBuilder(dirInfor.BaseDirectory, dirInfor.FileName); 

    if (typeof(TDirectoryBuilderFactoryImpl) == typeof(RiskDirectoryBuilderFactory)) 
    { 
     directoryBuilder = 
     () => CreateRiskDirectoryBuilder(ValuationDate, dirInfor.BaseDirectory, dirInfor.FileName); 
    } 
    return directoryBuilder; 
} 

private DirectoryBuilderInfo GetSettings(string baseName) 
{ 
    var settingsName = baseName.ToUpperInvariant(); 
    return new DirectoryBuilderInfo() 
    { 
     BaseDirectory = ConfigurationManager.AppSettings[settingsName + "_DIR"], 
     FileName = ConfigurationManager.AppSettings[settingsName + "_FILENAME"] 
    }; 
} 
+0

看起來不錯。有一件事:依賴倒置原則: - 你應該將'Func '傳入'BindDependencies'中,而不必使用特殊情況調用輔助函數。然後做一個超載,通過默認的並在大多數情況下使用它。如果你還沒有獲得manning.com/seemann – 2012-05-03 10:31:01

0

沒有理由依賴任何Ninject具體技術(儘管在某些情況下,Provider可能是合適的(example of a provider here)。

簡單的答案是,你創造了什麼綁定的前面部分的擴展方法表達式返回(similar question)。


在重新閱讀你的問題,我建議你看Ninject.Extensions.Conventions其中HASS很多Bind擴展方法,讓你做bullk在T Bind英格斯他建議你的方式。如果不是,我會建議評論和識別你覺得它沒有解決的位。

+0

喜魯本 - 可以請你提供一個簡單的例子或者一些指導開始在我的情況下使用擴展。我已經閱讀了Wiki,但沒有什麼真正打擊我作爲一個可行的解決方案。 – Ahmad 2012-05-02 07:41:42

+0

@Ahmad不是在說什麼地球震碎。步驟1只是一個方法,它包含了每個屬於3個綁定的塊。然後在那之後,如果剩餘時間/重複序列重複,則製作一個擴展方法,將兩者連接在一起。在EdNrrDirectoryBuilder中使用'ValuationDate'表明事情並不完全一致。經過反思,很難說您的配置順序是否足夠規範,以便適用慣例。將反饋刪除此答案很快,因爲您的問題太寬泛,無法獲得乾淨的答案。 – 2012-05-02 11:29:07

+0

我已經根據您的意見創建瞭解決方案 - http://stackoverflow.com/a/10429406/268667 – Ahmad 2012-05-03 10:21:35