ProgramingTip

단일성을 사용하여 명명 된 말을 생성자에 어떻게하면?

bestdevel 2020. 11. 11. 20:28
반응형

단일성을 사용하여 명명 된 말을 생성자에 어떻게하면?


I는 한 IRespository다음 코드 (이름)를 두 번 등록 :

// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
    ("Client", new InjectionConstructor(typeof(ClientEntities)));

// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
    ("Customer", new InjectionConstructor(typeof(CustomerEntities)));

IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();

하지만이 문제를 해결 비용 (을 사용하기 위해 위해 IRepository) 다음과 같은 수동 해결을 수행해야합니다.

public ClientModel(IUnityContainer container)
{
   this.dataAccess = container.Resolve<IRepository>(Client);

   .....
}

내가하고 싶은 것은 생성자에서 해결하는 것입니다 (처럼 IUnityContainer). 해결해야 할 명명 된 유형을 말할 방법이 필요합니다.

다음과 같이 : (참고 : 실제 코드가 아님)

public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
   this.dataAccess = dataAccess;

   .....
}

내 가짜 코드를 작동시키는 방법이 있습니까?


API, 속성에서 이름이 있거나 구성하거나 구성 파일을 통해 구성 할 수 있습니다. 위에서 XML을 사용하고 있다고 생각하지 않습니다.

에 명명 된 컨테이너 종속성을 해결하도록 지시하려면 InjectionParameter개체 를 사용해야 합니다. 예를 ClientModel들어 다음을 수행하십시오.

container.RegisterType<IClientModel, ClientModel>(
    new InjectionConstructor(                        // Explicitly specify a constructor
        new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
    )
);

이는 하나의 컨테이너에 "분석 할 때 ClientModel하나의 IRepository단일 변수를 사용 하는 것이 생성 호출 하십시오."

속성을 사용하려는 경우 거의 작동하며 속성 이름 만 변경됩니다.

public ClientModel([Dependency("Client")] IRepository dataAccess)
{
   this.dataAccess = dataAccess;

   .....
}

이것은 매우 늦은 응답이지만 여전히 Google에 질문이 표시됩니다.

어쨌든 5 년 후 ...

저는 아주 간단한 접근 방식을 가지고 있습니다. 일반적으로 "명명 한 표현"을 사용하는 경우에는 전략 패턴을 구현하려고합니다. 이 경우 Unity와 Unity에 StrategyResolver직접 의존하지 않도록 라는 나머지 코드 사이에 간접 수준을 생성합니다 .

public class StrategyResolver : IStrategyResolver
{
    private IUnityContainer container;

    public StrategyResolver(IUnityContainer unityContainer)
    {
        this.container = unityContainer;
    }

    public T Resolve<T>(string namedStrategy)
    {
        return this.container.Resolve<T>(namedStrategy);
    }
}

용법 :

public class SomeClass: ISomeInterface
{
    private IStrategyResolver strategyResolver;

    public SomeClass(IStrategyResolver stratResolver)
    {
        this.strategyResolver = stratResolver;
    }

    public void Process(SomeDto dto)
    {
        IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
        actionHanlder.Handle(dto);
    }
}

기재 :

container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();

이제 이것에 대한 좋은 점은 앞으로 새로운 전략을 추가 할 때 StrategyResolver를 다시는 만질 필요가 없다는 것입니다.

아주 간단합니다. 매우 깨끗하고 Unity에 대한 종속성을 최소한으로 유지했습니다. StrategyResolver를 만질 수있는 유일한 시간은 일어날 가능성이 거의없는 컨테이너 기술을 변경하기로 결정한 경우입니다.

도움이 되었기를 바랍니다!

편집 : Dependency서비스 생성자에서 속성 을 사용할 때 실제로 Unity에 대한 의존도가 높기 때문에 수락 된 답변이 맘에 들지 않습니다 . Dependency속성은 유니티 라이브러리의 일부입니다. 이 시점에서 IUnityContainer모든 곳 에서 종속성을 전달할 수 있습니다.

나는 내 서비스 클래스가 모든 곳에서 외부 라이브러리에 강한 의존성을 갖는 대신 내가 완전히 소유 한 객체에 의존하도록하는 것을 선호합니다. 또한 Dependency속성을 사용하면 생성자 서명이 덜 깨끗하고 간단 해집니다.

또한이 기술을 사용하면 생성자, 애플리케이션 구성 파일 또는 InjectionParameter디자인 타임에 사용할 명명 된 종속성을 알아야하는 모든 메서드를 사용하여 명명 된 종속성을 하드 코딩하지 않고도 런타임에 명명 된 종속성을 해결할 수 있습니다 .

편집 (2016-09-19) : 궁금 할 수있는 사용자 IUnityContainer를 위해 StrategyResolver생성자 서명에 표시된대로 종속성 으로 요청할 때 컨테이너가 자신을 전달하는 것을 알게됩니다 .

편집 (2018-10-20) : 단순히 공장을 사용하는 또 다른 방법이 있습니다.

public class SomeStrategyFactory : ISomeStrategyFactory
{
    private IStrategy _stratA;
    private IStrategy _stratB;

    public SomeFactory(IStrategyA stratA, IStrategyB stratB)
    {
        _stratA = stratA;
        _stratB = stratB;
    }

    public IStrategy GetStrategy(string namedStrategy){
        if (namedStrategy == "A") return _stratA;
        if (namedStrategy == "B") return _stratB;
    }
}

public interface IStrategy {
    void Execute();
}

public interface IStrategyA : IStrategy {}

public interface IStrategyB : IStrategy {}

public class StrategyA : IStrategyA {
    public void Execute(){}
}

public class StrategyB : IStrategyB {
    public void Execute() {}
}

용법:

public class SomeClass : ISomeClass
{
    public SomeClass(ISomeStrategyFactory strategyFactory){

        IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
        strat.Execute();

    }
}

기재:

container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();

이 두 번째 제안은 동일하지만 공장 디자인 패턴을 사용합니다.

도움이 되었기를 바랍니다!


ParameterOverrides를 사용할 수 있어야합니다.

var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );

편집 : 왜 UnityContainer를 넘나 드는지 잘 모르겠습니다. 개인적으로 생성자 자체에 종속성을 주입합니다 (내가 본 것에서 "정상"입니다). 그러나 관계없이 RegisterType 및 Resolve 메서드에 이름을 지정할 수 있습니다.

IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");

그 이름으로 등록한 유형을 제공합니다.


이러지 마세요-그냥 생성 class ClientRepository : GenericRepository { }하고 타입 시스템을 활용하세요.

참고 URL : https://stackoverflow.com/questions/7046779/with-unity-how-do-i-inject-a-named-dependency-into-a-constructor

반응형