2014-02-11 8 views
1

나는Ninject를 사용한 부분 주입?

내가 ISomething를 주입하는 로직을 변경하려면
public MyClass(bool val) //[OPTION 1: Current] 
{ 
    //I Called static function to do something -> I want to inject this 
    ... 
    if(val){ ... } else{ ... } 
    ... 
} 

.... ctor에 모양을 생성자에서 부울 매개 변수가 기존의 클래스에 Ninject에 구현하기 위해 노력하고 같은 :

public MyClass(ISomething something, bool val) //[OPTION 2: Desired] 
{ 
    something.DoSomething(); 
    ... 
    if(val){ ... } else{ ... } 
    ... 
} 

나는 또한 이것을 다음과 같이 불리는 일회용 클래스를 사용했다 : [예. 사용 옵션 1 -> 옵션 2]

public MyMaster(bool val) 
{ 
    this.myclass = new MyClass(val); //-> now this has to be injected, how??? 
} 

내가 구현 변환하려고이 같은 true 또는 false 매개 변수로 using 맥락에서 몇 번, 그 : [예. 사용 옵션 1 -> 내가 하나 개의 값을 주입하고 다른를 주입하지해야하기 때문에 ... 옵션 2]

내가 가지 여기 차단하고
using(var master = new MyMaster(true)){...} //-> This need to be refactored or injected, how??? 
//... 
using(var master = new MyMaster(false)){...} //-> This need to be refactored or injected, how??? 

로 변환하려고합니다. 어쩌면 런타임 인젝션을 구현합니까? 또한 필요한 경우 using 성명서에 포장 하시겠습니까?

참고 : 이것은 당신이 new 키워드를 사용할 때 .. 당신은 의존성 삽입 (Dependency Injection)을 포기하고, 일반적으로 (Ninject 나중에 레이어에 있습니다)

+0

나는'true '값 ('MyClass1')을 가진 클래스와'false' ('MyClass2')를 가진 클래스 두 개를 생성하려고 생각하고있다. 'false' 대신'MyClass1' 또는'MyClass2'를 사용 하겠지만, 정확하지 않고 확장 성이없고 지저분하지 않습니다. – Jaider

+0

하나의 해결책을 찾았지만 하위 계층에'Ninject'가 필요합니다 : http://stackoverflow.com/a/10821678/480700 – Jaider

답변

0

는 내가 제대로 질문을 이해 희망?

이렇게하려면 추상 팩터 리를 사용할 수 있습니다.(참고 : Simon Whitehead이 지적했듯이 Ninject 팩토리 확장을 사용하면 명확하게 나타낼 수 있습니다.)

이러한 인터페이스/클래스는 이 아니며에 정의되어 있습니다. 컴퍼넌트의 루트

public interface IMyClassFactory 
{ 
    IMyClass Create(bool val); 
} 

public interface IMyClass 
{ 
    //whatever methods, etc, it's supposed to have. 
} 

public class MyClass:IMyClass 
{ 
    public MyClass(bool val) 
    { 
     //do something with val here in the ctor 
    } 
} 

이 클래스는 당신이 당신의 일반적인 바인딩 할 때마다 당신이 당신의 구성 루트의 클래스를 결합

public class MyClassFactory:IMyClassFactory 
{ 
    readonly IKernel _kernel; 
    public MyClassFactory(IKernel kernel) 
    { 
     _kernel=kernel; 
    } 
    public IMyClass Create(bool val) 
    { 
     return _kernel.Get<IMyClass>(new ConstructorArgument("val",val); 
    } 
} 

그런 다음 구성 루트에 을 정의 :

kernel.Bind<IMyClassFactory>().To<MyClassFactory>(); 
kernel.Bind<IMyClass>().To<MyClass>(); 

와 당신 MyMaster 생성자는 다음과 같이 나타납니다.

이 작업을 진행하고, 제안 그들은 당신이 공장 클래스 자신 : (예 here)

를 작성하지 저장, 당신은 그것을 멀리 던져과 Ninject에 공장 확장을 사용할 수있는 방법을 작동 이해하면

+0

당신이 대답 하는게 올바른 방향이라고 생각합니다.하지만, 당신은'MyMaster', 주사를 어떻게 인스턴스화합니까? 또는 주입 된 팩토리를 단순히 통과시키고'new MyMaster (val, myInjectedFactory)'를 사용하면됩니까? – Jaider

+0

글쎄 그것은 달려있다; MyMaster 자체가 다른 클래스 (MVC 컨트롤러 등)의 의존성이라면 컨트롤러'ctor'에 인터페이스로 선언하고 컴포지션 루트에 'Bind '을 선언합니다. MVC 등을 사용하지 않고 그냥 오래된 Ninject (콘솔 앱 등)를 사용하고 있지 않다면, 애플리케이션의 어느 시점에서, 콘솔 애플리케이션의 경우 'Main()'인 컴포지션 루트 인 경우, var master = kernel. (새로운 ConstructorArgument ("val", val))'수동으로 가져 오십시오. 희망이 맞는가? –

1

주입에 대해 아무것도 모르는 클래스 라이브러리에서 이루어집니다.

당신이 "주입에 대해 아무것도 모르는 클래스 라이브러리 (Ninject는 최신 레이어 임)"에서 말한 것을 알고 있습니다.하지만 합성 루트는 루트 여야합니다. 그 말은, DI 부트 스트래핑이 최상위 계층에서 일어나야한다는 것입니다 (일반적으로 다른 프로젝트를 참조하는 별도의 프로젝트에서).

일단 설치가 끝나면 Ninject.Factories 확장 프로그램 사용에 대해 생각해 볼 수 있습니다. 따라서 당신에게 Ninject에 당신을 위해 인스턴스를 인스턴스화가 할 수있는 기능을 제공 어딘가에 주입하는 공장을

public interface ObjectCreatorFactory { 
    MyClass CreateInstanceOfMyClass(); 
    MyMaster CreateInstanceOfMyMaster(); 
} 

을 .. 그리고이 :이 같은 공장을 만들 수 있습니다.

유일한 대안은 좋은 이전 버전으로 되돌리기입니다. Service Locator. 필자는 테스트 구현에서 DI 컨테이너를 사용해야하는 경우 단위 테스트를 어렵게 만듭니다.

불행히도 이러한 옵션 만 사용할 수 있습니다. Ninject가해야 할 일을 수행하기를 바랄 수있는 방법이 없습니다. 말할 필요가 있습니다. 그것은 현재 당신이 일을 어떻게하고 있는지에 대한 변화를 포함합니다. 맞나요, Ninject 당신을 위해 그것을 공급이 당신이 MyMaster 생성자에 전달 된 bool에 따라 MyClass해야하고, 대신 new하지만 사용을 피하려면 -

+0

'new' 키워드는 DI에서 이동하려고 시도하고 있습니다. – Jaider

+0

맞아요, 그래서 당신은 애플리케이션을 어떻게 부트 스트랩할지 다시 생각해야합니다. 제가 말했듯이, 모든 것이 부트 스트랩 된 "합성 루트"는 일반적으로 응용 프로그램의 최상위 계층에 있으므로 모든 경로를 부트 스트랩 할 수 있습니다. 일단 그 자리에 있으면 주입은 사소한 것이되고 특히 Ninject Factories 확장을 사용하면 사소 해집니다. –

관련 문제