2010-06-23 7 views
14

다음 코드를 고려하십시오.Ninject에서 인터페이스의 배열 삽입

public interface IFoo { } 


public class Bar 
{ 
    public Bar(IFoo[] foos) { } 
} 


public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo[]>().ToConstant(new IFoo[0]); 
     // ToConstant() is just an example 
    } 
} 


public class Program 
{ 
    private static void Main(string[] args) 
    { 
     var kernel = new StandardKernel(new MyModule()); 
     var bar = kernel.Get<Bar>(); 
    } 
} 

프로그램을 실행하려고하면 다음 예외가 발생합니다. IFoo
일치하는 바인딩을 사용할 수 없으며, 유형 자기 바인딩되지 않습니다 활성화

오류가 발생했습니다.
활성화 경로 : 형 바
1) 바

요청의 생성자 파라미터 FOOS에 종속 IFoo의
2) 주입

어떻게해서 Ninject의 배열/바인드를 주입 ​​할 수 있는가?

감사합니다.

편집 :
내 응용 프로그램은 타사 구성 요소에서 생성 한 데이터를 가져옵니다. 가져 오기 프로세스가 다른 종류의 필터 (예 : 다른 필터 인터페이스 구현)를 적용합니다. 필터링 규칙은 매우 자주 변경되지만 순수 구성 (및 마스터 필터)을 수행하기에는 너무 복잡합니다.

가능한 한 쉽게 추가/편집 필터를 만들고 싶습니다. 내가 가진 것은 모든 필터 구현이 들어있는 어셈블리입니다. 모든 필터 인터페이스를 (해당 필터 유형의 모든 구현 인스턴스를 제공하는) 다음 메소드에 바인딩하려고했습니다. 기본적으로 필터 클래스를 추가/제거 할 때 Ninject 모듈을 변경할 필요가 없습니다.

private IEnumerable<TInterface> GetInterfaceImplementations<TInterface>(IContext context) 
    { 
     return GetType().Assembly.GetTypes() 
      .Where(t => typeof (TInterface).IsAssignableFrom(t) && IsConcreteClass(t)) 
      .Select(t => Kernel.Get(t)).Cast<TInterface>(); 
    } 

컨테이너 DI 메커니즘을 우회하는 측면에서 다소 죄책감을 느낍니다. 이것은 나쁜 습관입니까? 그런 일을하는 일반적인 관행이 있습니까?

해상도 : bsnote이 제안
나는 래퍼 클래스를 사용합니다.

답변

7

이것은 @ bsnote의 답변 (주로 1d에 해당)의 재 설명으로이 방식으로 작동하는 이유를 이해하는 데 도움이 될 수 있습니다.

Ninject에 (다른 DI/추가 기능 프레임 워크) 두 가지 기능을 가지고 :

  1. 하나를 얻을 수있는 서비스의 하나의 명확한 구현에 바인딩 (Get)
  2. 시설 중 하나의 개념 서비스 [하나가 다음 프로그램 중 하나를 선택합니다 또는 어떤 식 으로든에서 집계 (Ninject에의 GetAll/ResolveAll)

귀하의 예제 코드는 싸이를 사용하는 일의 집합 위의 2.와 관련된 ntax입니다. (예 :, MEF에서는 일반적으로 [ImportMany] 주석을 사용하여이 내용을 명확하게합니다.

샘플을 살펴볼 필요가 있습니다. @bsnote 말한대로

그러나, 귀하의 요구 사항을 리팩토링하는 방법 중 하나는 컨테이너에 배열 중 하나를 포장, 또는 당신이 그것을 요청 객체를 가지고있다 (즉, 팩토리 메소드 또는 저장소 형 구조)

실제 사례가 무엇인지 설명하는 것이 유용 할 수 있습니다. 왜 누드 배열이 있습니까? 분명히 모든 항목의 캡슐화를 요청하는 구성 요소 모음이 있습니다.이 질문은 분명히 많이 나오지 않습니다.

EDIT : 내가 생각하는 확장 기능에 스캔 예제가 있습니다 (StructureMap과 같은 경우에는 이런 종류의 것들이 더 통합되어 있습니다. 분명히 장점이 있습니다.) 죄수).

컨벤션 이상의 컨벤션 달성 여부에 따라 각 유형의 플러그인에 마커 인터페이스를 부착하는 것이 좋습니다. 그런 다음 각각 Bind을 명시 적으로 지정할 수 있습니다. 또는 CoC의 경우 생성 된 구현 집합에 ModuleLoad() 루틴을 반복 (즉, 많은 개별 Get) 할 수 있습니다.

어느 쪽이든, 여러 번 등록하면 행복하게 T[] 또는 IEnumerable<T>을 요청하고 전체 세트를 얻을 수 있습니다. 이를 명시 적으로 달성하고자한다면 (예 : Service Locator와 그 모든 것이 암시하는 것처럼) GetAll을 사용하여 일괄 적으로 배치 할 수 있으므로 사용자가 수행 한 방식에서 내포적인 루핑을 수행하지 않을 수 있습니다.

이 연결을했습니다 아니면 내가 뭔가를 누락하는 경우 어느 쪽이든을, 나는 그것이> 1000 개 단어를 말하는대로 질문에 몇 가지 코드를 부착 할 수 가르쳐 바란다 경우 확실하지 :.

+0

자세한 내용은 답변을 선택했습니다. 감사합니다 (+1) to bsno 테도! –

4

나에게도 문제가있었습니다. Ninject는 배열 자체 대신 배열의 각 항목을 삽입하므로 배열 항목 유형에 대해 정의 된 매핑이 있어야합니다. 사실 Ninject의 현재 버전과 함께 배열을 배열로 매핑 할 수있는 가능성은 없습니다. 해결 방법은 배열 주위에 래퍼를 만드는 것입니다. 예를 들어 게으른 클래스를 사용할 수 있습니다. 또는 독자적인 래퍼를 만들 수도 있습니다.

관련 문제