2014-11-14 95 views
1

我有一個課前我介紹了一個看起來像這樣的依賴注入:Ninject與一次性對象使用(重置對象屬性)

public class Widget 
{ 
    public Widget Create() 
    { 
     using (DataProvider dataProvider = new DataProvder()) 
     { 
      dataProvider.AddInput("name", name); 
      dataProvider.AddInput("path", path); 
      dataProvider.AddInput("dateCreated", DateTime.UtcNow); 

      using (var reader = _dataProvider.ExecuteReader("usp_widget_create")) 
      { 
       reader.Read(); 
       return new Widget(reader); 
      } 
     } 
    } 
} 

然後我介紹了使用Ninject依賴注入和我的課,現在看起來是這樣的所以我不創建對DataProvider類的依賴。

public class Widget 
{ 
    IDataProvider _dataProvider; 

    public Widget(IDataProvider dataProvider) 
    { 
     _dataProvider = dataProvider; 
    } 

    public Widget Create() 
    { 
     _dataProvider.AddInput("name", name); 
     _dataProvider.AddInput("path", path); 
     _dataProvider.AddInput("dateCreated", DateTime.UtcNow); 

     using (var reader = _dataProvider.ExecuteReader("usp_widget_create")) 
     { 
      reader.Read(); 
      return new Widget(reader); 
     } 
    } 
} 

新類的問題是,一個,一個DataProvider不會得到處置和二,向DataProvider的屬性將不會被重置。所以如果我從同一個對象兩次調用Create,它會複製參數並拋出一個異常。我知道我可以通過清除參數來明確地解決第二個問題,但是我覺得必須有更通用的方法,並且我錯過了一些東西。

這種情況應該如何解決?

回答

1

非常想要利用的模式是依賴注入Abstract Factory Pattern。 這個工廠模式允許您在需要時dynamically create instances。這樣做是非常普遍的事情。

定義一個工廠,允許您創建Provide實例。

public interface IProviderFactory 
{ 
    T Create<T>(); 
} 

執行過程可以很簡單,如下所示。

public class ProviderFactory : IProviderFactory 
{ 
    private readonly IKernel _kernel; 

    public ProviderFactory(IKernel kernel) 
    { 
     _kernel = kernel; 
    } 

    public T Create<T>() 
    { 
     var instance = _kernel.Get<T>(); 
     return instance; 
    } 
} 

現在改變你的Widget接受工廠,而不是IDataProvider的

public class Widget 
{ 
    readonly IProviderFactory _factory; 

    public Widget(IProviderFactory factory) 
    { 
     _factory = factory; 
    } 

    public Widget Create() 
    { 
     var provider = _factory.Create<IDataProvider>(); 

     provider.AddInput("name", "name"); 
     provider.AddInput("path", "path"); 
     provider.AddInput("dateCreated", DateTime.UtcNow); 

     //..... 
    } 
} 

注意,創建的每次調用()就解決了IDataProvider的新實例。

var provider = _factory.Create();

的籽粒註冊是類似下面..

 using (IKernel Kernel = new StandardKernel()) 
     { 
      Kernel.Bind<IDataProvider>().To<DataProvider>(); 
      Kernel.Bind<IProviderFactory>() 
      .To<ProviderFactory>().WithConstructorArgument(typeof(IKernel), Kernel); 
      var widget = Kernel.Get<Widget>(); 
      widget.Create(); 
      widget.Create(); 
     } 

東西沿線應該爲您的方向可能的解決方案。

+0

我的提供者在我的業務層,我的Ninject參考和聲明位於演示者(wpf應用程序)的堆棧頂層。我希望保留所有層,除了最頂層之外,不要引用Ninject。在所有圖層中調用Ninject是不可避免的? – Chris 2014-11-15 13:41:16

+1

改爲使用ninject.extensions.factory。 'IProviderFactory'保持不變,並且綁定到'Bind ()。ToFactory()'。你可以擺脫實施。或者,使用相同的擴展名,但只是注入一個'Func ' – BatteryBackupUnit 2014-11-15 17:22:46

+0

這聽起來像我得到的,但我認爲我需要看到一個例子來充分理解。對不起,我是新手。 – Chris 2014-11-15 19:02:18