GetAllInstances를 호출 할 때 장식 된 인스턴스의 기본 구현 유형을 발견하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/19825921

문제

이 코드가 있습니다.

using (container.BeginLifetimeScope())
{
    RenderWord instruction = new RenderWord();
    var instances = container.GetAllInstances<IInstructionHandler<RenderWord>>();
    var firstInstance = result.First();
}

instances 유형입니다 IEnumerable<IInstructionHandler<RenderWord>>

firstInstance 유형입니다 IInstructionHandler<RenderWord> 그것은 실제로 다른 데코레이터를 장식하는 다른 데코레이터를 장식하는 데코레이터의 인스턴스입니다 ...

런타임에 실제 클래스 instances 유형입니다 ContainerControlledCollection<IInstructionHandler<RenderWord>>ContainerControlledCollection 클래스는 매우 유용한 정보를 보유합니다 - 기본 ImplementationType.

내가 갈 수있는 방법이 있습니까? ContainerControlledCollection 아니면 그 producers[0].Value.ImplementationType 런타임에 데코레이터 체인 아래의 기본 구현 유형을 실제로 발견 할 수 있기를 원했기 때문입니다.

도움이 되었습니까?

해결책

@atomaras는 당신의 추상화에 대해 좋은 지적을 가질 수 있다고 생각합니다. 비록 구성 루트가 시스템의 모든 구현을 이미 알고 있기 때문에 구성 루트 내 에서이 정보 만 사용할 때 괜찮을 것이라고 생각합니다.

이 정보를 얻을 수있는 몇 가지 방법이 있다고 생각합니다.

  1. 사용 DecoratorPredicateContext 제공되는 정보 RegisterDecorator 확장 방법 :

    var typeMapping = new Dictionary<Type, Type>();
    
    container.RegisterDecorator(typeof(IInstructionHandler<>), typeof(FakeDecorator<>), c =>
    {
        typeMapping[c.ServiceType]  = c.ImplementationType;
        // or perhaps even use c.AppliedDecorators property to see which decorators 
        // are applied.
    
        // return false to prevent the decorator from being applied.
        return false;
    });
    

    간단한 인젝터가 모든 것을 요구할 수있는 가짜 등록을 할 수 있습니다. IInstructionHandler<T> 시스템에서는 항상 반환되는 술어를 공급하여 적용되는 것을 방지합니다. false. 간단한 인젝터가 제공하는 정보를 DecoratorPredicateContext 실제 구현 유형이 무엇인지 알아 내기 위해.

또는 AN을 주입 할 수 있습니다 DecoratorContext 인스턴스 (v2.6 이상) 가장 인스턴스 (설명 된대로 여기). 그만큼 DecoratorContext 동일한 정보를 포함합니다 DecoratorPredicateContext 이 객체는 간단한 인젝터에 의해 자동으로 의존하는 데코레이터에 자동으로 주입됩니다. 그것은 당신이 당신의 경우에 매우 편리 할 수있는 데코레이터 내부에서 결정을 내릴 수 있습니다.

  1. AN을 추가하십시오 IDecorator 데코레이터 체인을 가로 지르는 시스템에 대한 추상화.

    각 데코레이터가 구현하도록함으로써 a IDecorator 장식용에 액세스 할 수있는 인터페이스 (완료된대로 여기) 데코레이터 체인을 가로 지르고 실제 구현 유형을 찾을 수 있습니다.

    public interface IDecorator
    {
        object Decoratee { get; }
    }
    
    public static class DecoratorHelpers
    {
        public static IEnumerable<object> GetDecoratorChain(IDecorator decorator)
        {
            while (decorator != null)
            {
                yield return decorator;
    
                decorator = decorator.Decoratee as IDecorator;
            }
        }
    }
    

    다음과 같이이 인터페이스를 사용하여 데코레이터를 구현할 수 있습니다.

    public class SomeDecorator<T> : IInstructionHandler<T>, IDecorator
    {
        private readonly IInstructionHandler<T> decoratee;
    
        public SomeDecorator(IInstructionHandler<T> decoratee)
        {
            this.decoratee = decoratee;
        }
    
        object IDecorator.Decoratee { get { return this.decoratee; } }
    }
    

    모든 데코레이터 에서이 인터페이스를 구현하면 다음을 수행 할 수 있습니다.

     var implementationTypes =
         from handler in container.GetAllInstances<IInstructionHandler<RenderWord>>()
         let mostInnerDecorator =
             DecoratorHelpers.GetDecoratorChain(handler as IDecorator).LastOrDefault()
         let implementation = mostInnerDecorator != null ? mostInnerDecorator.Decoratee : handler
         select implementation.GetType()
    
  2. 목록을 등록하십시오 Registration 하나의 인스턴스 RegisterAll 과부하 Registration 객체는 실제 구현 유형에 대해 알고 있습니다.

  3. 그러나 지점 3 대신 해당 등록을 작성하는 데 사용한 구현 유형 목록을 사용할 수도 있습니다.

    typeMapping[serviceType] = implementationTypes;
    container.RegisterAll(serviceType, implementationTypes);
    

    간단한 인젝터는 등록 된 구현을 등록 된 것과 동일한 순서로 항상 해결합니다 (보장됩니다). 따라서 사물 모음을 해결할 때 이미 동일한 순서로 배치 된 구현 목록이 있습니다.

다른 팁

왜 첫 번째 유형의 유형을 확인하지 않습니까? 그것이 당신에게 실제 구현 유형을 제공하지 않습니까? 구현 유형을 알아야한다는 사실은 추상화와 관련된 문제를 잘 나타내는 것이라고 말해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top