5

문자열과 같은 일부 기본 형식 인수가 생성자에있는 클래스가 있습니다원시 인수 생성자로 유형을 등록 하시겠습니까?

형식을 유니티 컨테이너에 어떻게 등록해야합니까?

public LoginManager(
    IRegionManager regionManager, 
    IEventAggregator eventAggregator, 
    string mainRegionName, 
    Uri login, 
    Uri target) 
    { 
    this.regionManager = regionManager; 
    this.eventAggregator = eventAggregator; 
    this.mainRegionName = mainRegionName; 
    this.login = login; 
    this.target = target; 
    } 
} 

업데이트 다음 IRegionManagerIEventAggregator 내 경우에 컨테이너 래퍼 프리즘 UnityBootstrapper에 유형을 알고 있는지
Remeber. 나는 그들을 다시 등록해야합니까 ?? 나는 형식 등록을 가능한 한 간단하게 유지하기를 원한다.

나쁜 습관으로 간주 되나요? 더 좋은 대안?

답변

12

솔직히 말해서, 나는 생성자에서 타입을 해결할 수있는 원시적이거나 어려운 클래스 디자인을 갖지 않으려 고합니다. 이미 Tavares의 답변에서 보았 듯이 구성이 매우 약해집니다 (업데이트 : Tavares가 내게 명확하지 않은 이유로) 자신의 대답을 제거한 것으로 보입니다. 느슨한 컴파일 타임 지원은 해당 구성자를 변경할 때마다 DI 구성을 변경하게합니다.

이를 방지하기 위해 디자인을 변경하는 방법은 여러 가지가 있습니다. 어떤 사람이 당신을 위해 적용 당신에게 달려 있지만, 여기에 몇 가지 아이디어입니다 :

옵션 1 : 불변의 구성 DTO 사용

private sealed class LoginManagerConfiguration 
{ 
    public Uri Login { get; private set; } 
    public Uri Target { get; private set; } 
    public string MainRegionName { get; private set; } 

    public LoginManagerConfiguration(Uri login, Uri target, string mainRegionName) 
    { 
     this.Login = login; 
     this.Target = target; 
     this.MainRegionName = mainRegionName; 
    } 
} 

지금 당신이 할 수있는 당신의 LoginManager에 대한 종속성을 LoginManagerConfiguration는 :

public LoginManager(IRegionManager regionManager, 
    IEventAggregator eventAggregator, 
    LoginManagerConfiguration configuration) 
{ 
    ... 
} 

LoginManagerConfiguration은 단순히 다음과 같이 등록 할 수 있습니다 :

container.RegisterInstance<LoginManagerConfiguration>(
    new LoginManagerConfiguration(
     login: new Uri("Login"), 
     target: new Uri("Target"), 
     mainRegionName: ConfigurationManager.AppSettings["MainRegion"])); 

이 유형별 DTO 대신 응용 프로그램 차원의 구성 객체를 지정하는 것이 유혹적 일 수 있지만 이는 트랩입니다. 이러한 응용 프로그램 전반의 구성 개체는 서비스 로케이터 방지 패턴과 동일한 구성입니다. 형식에 필요한 구성 값이 무엇인지 명확하지 않게되고 클래스를 테스트하기가 더 어려워집니다.

옵션 2 : 그냥 DI 구성의 목적을 위해, 그 클래스

또 다른 옵션은 클래스에서 파생하는 것입니다에서 파생. 이것은 당신이 클래스 서명을 변경할 수없는 경우에 특히 유용합니다 (즉,이 타사 구성 요소의 경우) :

private sealed class DILoginManager : LoginManager 
{ 
    DILoginManager(IRegionManager regionManager, 
     IEventAggregator eventAggregator) 
     : base(regionManager, eventAggregator, 
      ConfigurationManager.AppSettings["MainRegion"], 
      new Uri("Login"), 
      new Uri("Target")) 
    { 
     ... 
    } 
} 

응용 프로그램의 구성 루트에 가까운이 클래스를 정의가.이 클래스는 DI 구성의 구현 세부 사항이됩니다. 당신의 유형의 등록은 지금 매우 간단합니다 :

container.RegisterType<ILoginManager, DILoginManager>(); 

통화로하지만 매우 조심 그러한 ConfigurationManager.AppSettings["MainRegion"] 게으른로드 구성 값. 이렇게하면 응용 프로그램을 시작하는 동안 구성 오류가 발생하지 않는 상황이 발생할 수 있습니다. 이는 실제로 바람직합니다.

옵션 3 : 사용 공장 대표

내가 제시 하 고 싶습니다 마지막 옵션은 공장입니다. 이것은 Traveses의 답과 비슷하게 보이지만 타입 안전합니다.

var mainRegion = ConfigurationManager.AppSettings["MainRegion"]; 

container.Register<ILoginManager>(new InjectionFactory(c => 
{ 
    return new LoginManager(
     c.Resolve<IRegionManager>(), 
     c.Resolve<IEventAggregator>(), 
     ConfigurationManager.AppSettings["MainRegion"], 
     new Uri("Login"), 
     new Uri("Target")); 
})); 

이 정보가 도움이되기를 바랍니다.

+0

InjectionFactory 접근법의 경우, 다음과 같이 해당 매개 변수를 허용하고 ILoginManager를 반환하는 InjectionFactory를 관련 지어 Func 유형을 등록 할 수도 있습니다. new InjectionFactory (c => (login, target , 새로운 ParameterOverride ("mainRegionName"), 새로운 ParameterOverride ("로그인", 로그인), 새로운 ParameterOverride ("target", target))))). 이 방법으로 해결하면 생성자에서 종속성에 대해 유연하게 유지할 수 있으며 원시 매개 변수 변경 만 위해 변경해야합니다. –

+1

아주 좋은 대답, btw. –

+0

추가하는 것을 잊었습니다 : 사용법은 Func 를 의존성으로 받아들이고 해당 매개 변수를 ILoginManager를 생성하는 함수로 전달하는 것입니다. 이들이 설정이라면 나는 스티븐의 접근법을 고수 할 것이지만, 특정 상황에서 바뀔 수있는 런타임 값이라면 이와 같은 일을해야 할 것이다. –

0

아니요. 나쁜 습관이 아닙니다. 그것은 완벽하게 유효한 시나리오입니다. Unity에서 옮겨온 지 몇 년이 지났지 만 머리 꼭대기에서 명시 적으로 원하는 생성자를 가리켜 야하고 모든 매개 변수를 열거하고 기본 객체에 대해서는 new ResolvedParameter("your value")을 수행해야합니다.

또한 Type 매개 변수가 있습니다. 그것은 Unity를 신중히 다루십시오 ... 그것들을 다루는 아주 놀라운 방법입니다. 나는 blogvost를 가지고있다. here.

+0

dziękuję. 제 업데이트 된 질문을보십시오. 제 사례에 대한 예를 보여 주시면 감사하겠습니다. BTW, 내 머리 꼭대기는 어딨어? 나는 그것이 힙이라고 생각한다? – Shimmy

+0

대다수의 경우 원시 변수에 ResolvedParameter를 명시 적으로 사용할 필요가 없습니다. –

관련 문제