0

Unity에서 Simple Injector로 이동하려고하고 Injection이 Simple Injector로 작업하는 데 문제가 있습니다.여러 생성자로 제네릭 타입 등록

작업 유니티 코드가

var container = new UnityContainer(); 
DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 

container.RegisterType(
    typeof(ICacheManager<>), 
    new ContainerControlledLifetimeManager(), 
    new InjectionFactory((c, targetType, name) => 
     CacheFactory.FromConfiguration(targetType.GenericTypeArguments[0], "myCache"))); 

내 시도 아래 : 만들 수 있도록

var registration = Lifestyle.Singleton.CreateRegistration(
    typeof(ICacheManager<>), 
    typeof(BaseCacheManager<>), 
    container); 

container.AddRegistration(
    serviceType: typeof(BaseCacheManager<>), 
    registration: registration); 

내가 용기를 들어 다음과 같은 오류

을 얻고있다 BaseCacheManager<Object>이 있어야한다 하나의 공용 생성자

+0

유형에 생성자가 하나만 있는지 확인해야합니다. 다른 생성자를 제거하십시오. – Steven

+0

답장을 보내 주신 Steve에게 감사드립니다. 캐싱을 돕기 위해 CacheManager.net의 외부 라이브러리를 사용하고 있습니다. 두 번째 생성자를 제거하는 것 외에는 다른 대안이 있습니까? –

+0

DI 프레임 워크를 사용할 수 없습니까? 심지어 새로운 경량의 MS (dotnet core)도 처리 할 수 ​​있습니다. 클래스에 대해 단 하나의 공용 ctor를 허용하는 것은 매우 큰 제한입니다. ~~ – MichaC

답변

1

Simple Injector에서이를 해결할 수있는 몇 가지 방법이 있습니다.

우선, 항상 구성 요소에 단일 생성자가 있습니다 (multiple constructors is an anti-pattern).

그러나 제공된 유형은 외부 라이브러리에서 가져온 것이므로 변경할 수 없습니다.

대신 할 수있는 것은이 특정 유형에서 파생되며 하나의 생성자 만 가진 하위 클래스를 만드는 것입니다. 이것은이기 때문에, 당신은 응용 프로그램에서 정의되지 않은 추상화에 의존하는 응용 프로그램 코드를 필요가 없도록해야한다, 그러나 일반적으로

class MyBaseClassManager<T> : BaseCacheManager<T> 
{ 
    public MyBaseClassManager([args]) : base([args]) { } 
} 

container.RegisterSingleton(typeof(ICacheManager<>), typeof(MyBaseCacheManager<>)): 

:이 유형은 관심있는 기본 클래스의 특정 생성자로 호출 할 수 있습니다 Dependency Inversion Principle (DIP) 위반. DIP은 애플리케이션 맞춤형 추상화를 정의합니다. 이러한 추상화에 따라 외부 구성 요소로 호출을 전달하는 어댑터를 정의 할 수 있습니다. 예 : here를 설명한 바와 같이,

container.RegisterSingleton<ICacheManager<Foo>>(new BaseCacheManager<Foo>());  
container.RegisterSingleton<ICacheManager<Bar>>(new BaseCacheManager<Bar>());  
container.RegisterSingleton<ICacheManager<FooBar>>(new BaseCacheManager<FooBar>());  

는 또 다른 옵션은 생성자 해상도 동작을 재정의하는 것입니다 : 당신이 필요로하는 폐쇄 유형의 수에 제한이있는 경우

// In the application's core layer 
public interface ICache<T> 
{ 
} 

// Adapter in the Composition Root 
public sealed class CacheManagerCacheAdapter<T> : ICache<T> 
{ 
    private static BaseCacheManager<T> manager = new BaseCacheManager<T>(); 

    // Implement ICache<T> methods 
    public object GetByKey(object key) 
    { 
     // translate and forward to the external component 
     return this.manager[key]; 
    } 
} 

// Registration 
container.RegisterSingleton(typeof(ICache<>), typeof(CacheManagerCacheAdapter<>)): 

, 당신은 명시 적으로 모든 폐쇄 된 버전을 등록 할 수 있습니다. 이

public class CacheManagerConstructorResolutionBehavior 
    : IConstructorResolutionBehavior { 
    private readonly IConstructorResolutionBehavior org; 
    public CacheManagerConstructorResolutionBehavior(IConstructorResolutionBehavior org) { 
     this.org = org; 
    } 
    public ConstructorInfo GetConstructor(Type serviceType, Type implementationType) { 
     if (implementationType.IsGenericType && 
      implementationType.GetGenericTypeDefinition() == typeof(BaseCacheManager<>)) { 
      return implementationType.GetConstructors() 
       .OrderByDescending(c => c.GetParameters().Length) 
       .First(); 
     } 
     return this.org.GetConstructor(serviceType, implementationType); 
    } 
} 

var container = new Container(); 
container.Options.ConstructorResolutionBehavior = 
    new CacheManagerConstructorResolutionBehavior(
     container.Options.ConstructorResolutionBehavior); 

는 또 다른 옵션은 내가에만이 같은 최후의 수단을 권합니다 있지만 ResolveUnregisteredType` event 사이에 끼어하는 것입니다 수 있습니다.

+0

감사합니다. 스티븐,이 질문에 대답 해 주신 시간에 정말 감사드립니다. CacheManager 라이브러리가 DIP를 위반하고 있기 때문에 필자는 다른 구현을 조사하기 시작했으며 https://github.com/exceptionless/Foundatio#caching을 발견했습니다. –

+0

안녕하세요 @WebbyWebDeveloper. 해당 도서관은 DIP를 위반하지 않고 있습니다. 귀하의 신청서는 응용 프로그램은 모든 라이브러리를 사용할 수 있지만 DIP은 응용 프로그램의 주 코드에서 해당 라이브러리를 숨길 수 있도록 안내합니다. – Steven

+0

단지 참고 사항 : BaseCacheManager는 라이브러리의 다음 버전에 하나의 ctor 만 갖습니다. 나는 그것을 며칠 전에 바 꾸었습니다. 사실 지금 당장 우스개 소리가납니다.) 그런데, 일반적으로 나는 여러 ctor가 문제가되는 것에 완전히 동의하지 않습니다. 항상 타사 라이브러리를 다루어야하며 DI 프레임 워크는 결코 이러한 제약 조건을 적용해서는 안됩니다. 다행히도 이러한 프레임 워크가 많이 있으며, 또 하나를 선택할 수 있습니다 ^^ – MichaC

관련 문제