2011-12-05 4 views
6

I가로드 오버라이드에 다음 (아래 손질) 로직이있는 Autofac 모듈 :정지 Autofac 모듈 등록 이미 등록 된 구성 요소

protected override void Load(ContainerBuilder builder) 
    { 
     foreach (var componentType in allTypesInAllAvailableAssemblies) // Set elsewhere 
     { 
      var handlerInterfaces = componentType.GetInterfaces().Where(i => i.IsClosedTypeOf(typeof(IMessageHandler<>))); 
      if (handlerInterfaces.Any()) 
       builder.RegisterType(componentType).As(handlerInterfaces); 
     } 
    } 

이 자체가 메시지 처리기를 선언하는 클래스를 찾고 및 구현하고있는 모든 IMessageHandler 인터페이스에 등록합니다.

내가 원하는 것은 이 아닙니다.은 이미 등록 된 구성 요소를 등록합니다. 보너스로, 이미 존재하지 않는 경우 기존 등록을 업데이트하여 메시지 처리기 인터페이스에 대해 해결할 수 있다면 이상적입니다. 이 코드는

내가에 등록 조작에 대한 AttachToComponentRegistration 재정의를 사용했습니다 (가능한 메시지 핸들러 후보 포함) 등록 된 후 모든 다른 유형을 실행하는 것으로 가정 할 수있다 인수를 위해서

과거이지만이 시나리오에서는 유용하지 않은 것처럼 보입니다.

내 디자인을 다시 생각해보고 플러그인이 명시 적으로 핸들러를 선언하도록해야합니까?

+0

AnyConcreteTypeNotAlreadyRegisteredSource 클래스를 사용해 보셨습니까?참조 : http://stackoverflow.com/questions/3413660/ –

답변

7
builder.RegisterType(componentType) 
    .As(handlerInterfaces) 
    .PreserveExistingDefaults(); 

처리기 목록 해결을 시작하지 않으면 작동합니다.

+0

불행히도 핸들러 목록이 필요합니다. 모든 유형의 다른 스윕을 수행하는 대신 유형이 명시 적으로 등록 될 때 모든 핸들러 인터페이스를 찾기 위해 파견 등록을 변경했습니다. 건배에 대한 환호 - 내가 질문을 답변을 게시 한 이후로 받아 들였습니다. – JRoughan

1

불행히도 원하는 것을 할 수있는 우아한 방법이 없습니다. Autofac 컨테이너와 그 빌더는 이미 가지고있는 것을 잘 볼 수없는 "블랙 박스"입니다.

등록이 주문에 따라 다르면 (BAD, BAD, BAD) 등록을 두 번 등록하는 데 아무런 해가 없습니다. 두 번째 시간을 등록하면 기존 등록을 새 것으로 덮어 씁니다.

이 코드는 완전히 allTypesInAllAvailableAssemblies가 초기화되는 방식에 따라 달라 지므로이 코드에 심각하게 질문합니다. 시스템에 실제로 모든 유형이 있다면, IDisposable로 해결 될 것이 무엇인지에 관해서는 헛소리입니다. IConfigurator에 대한 여러 가지 구현이 있다면 이미 등록 된 항목을 확인하는지 또는 등록을 덮어 쓰는 지 여부와 관계없이 어느 항목이 등록되어 있는지에 대한 제어가 제한됩니다. 그것은 어떤 클래스가리스트에서 처음으로 (또는 마지막으로) 끝나는 지에 전적으로 달려 있습니다.

protected override void Load(ContainerBuilder builder) 
{ 
    foreach (var componentType in allTypesInAllAvailableAssemblies.OfType<Type>().Distinct()) // Set elsewhere 
    { 
     var handlerInterfaces = componentType.GetInterfaces().Where(i => i.IsClosedTypeOf(typeof(IMessageHandler<>))); 
     if (handlerInterfaces.Any()) 
      builder.RegisterType(componentType).As(handlerInterfaces); 
    } 
} 

이 componentType가 각 인스턴스가 본 적이 보장됩니다 :

내가하고 생각할 수있는 유일한 방법은 당신이 등록하는 형식의 목록이 고유한지 확인하기 위해 약간의 Linq에를 사용하는 것입니다 전에이 빌더에 의해,이 foreach 루프의 범위 내에서. 이것은 이것이 컨테이너를 작성하는 데 사용되는 유일한 모듈이며 각 컨테이너가 한 번만 빌드되고 갱신되지 않는다는 것을 감안할 때 시스템의 각 구성 요소는 주어진 컨테이너에 정확히 한 번 등록됩니다. IDisposable, IEnumerable, IComparable, IComparer 등과 같은 공용 인터페이스는 해결하려고 시도 할 가치가 없습니다. 그들은 그 인터페이스를 가진 마지막 클래스의 인스턴스로 해석 할 것입니다.

ContainerBuilder를 사용하여 기존 컨테이너를 Update() 할 때 인터페이스가 등록되지 않았거나이 코드가 작동하는지 확인해야하는 경우 절망적 인 컨테이너를 만들려고하기 때문에 수행중인 작업을 중지하십시오. 엉망으로 제대로 유지할 수 없게됩니다.

+0

플러그인에 대한 이중 디스패치 등록 메커니즘 (즉, 등록 메소드를 노출하고 내부적으로 빌더에 추가하는 클래스가 제공됨)이 발생했습니다. 이것은 좋고 깨끗하며 핸들러를 등록하는 데 사용할 수 있지만 플러그인에서이 핸들러를 쉘에 명시 적으로 등록하지 않도록하는 방법을 찾고있었습니다. 구성 요소가 디스패치에 등록되어 있지만 메시지 처리기 인 경우 (특히 수명이 다른 경우)에는이 기능도 정상적으로 작동합니다. – JRoughan

+0

시스템에 존재하는 여러 개의 인터페이스에 문제가 없습니다 (실제로 예상됩니다). 또한 기존 컨테이너를 갱신하거나 등록의 순서 종속성이 없습니다. 아마 시나리오를 설명하지 않았을 수도 있지만 생각만큼 나쁘지는 않습니다. – JRoughan

+0

아, allTypesInAllAvailableAssemblies는 SO 샘플에만 존재합니다. 실세계에서는 사용 가능한 유형이 다른 클래스에서 제공되며 여기에 스마트가 포함됩니다. – JRoughan

관련 문제