2014-11-14 1 views
1

I 적이있는 클래스 I는이처럼 보였다 종속 분사를 도입하기 전에 : 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; 
    } 
} 

지금 만들기의 각 호출()가 IDataProvider의 새로운 인스턴스를 해결할 것이라는 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); 

     //..... 
    } 
} 

주 공장을 허용하도록 위젯을 변경합니다.

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

+1

대신 ninject.extensions.factory를 사용하십시오. 'IProviderFactory'도 동일하게 유지되고'Bind (). ToFactory()'와 결합됩니다. 구현을 제거 할 수 있습니다. 또는 동일한 확장자를 사용하지만'Func ' – BatteryBackupUnit

+0

을 삽입하십시오. 내가 생각하는 것처럼 들리지만, 완전히 이해하려면 예제를 볼 필요가 있다고 생각합니다. 미안 해요, 이거 처음이에요. – Chris

관련 문제