2014-06-23 2 views
4

Ninject에서 구성 할 수있는 동작을 에뮬레이트하려고하는데 대신 Unity 만 사용하십시오. 콘크리트 유형을 기반으로 한 Unity의 일반 유형 등록

나는 다음과 같은 클래스와 인터페이스를 제공, 캐시 된 저장소 패턴을 사용하려고 시도하고있다 :

public interface IRepository<T> 
{ 
    T Get(); 
} 

public class SqlRepository<T> : IRepository<T> 
    where T : new() 
{ 
    public T Get() 
    { 
     Console.WriteLine("Getting object of type '{0}'!", typeof(T).Name); 
     return new T(); 
    } 
} 

public class CachedRepository<T> : IRepository<T> 
    where T : class 
{ 
    private readonly IRepository<T> repository; 

    public CachedRepository(IRepository<T> repository) 
    { 
     this.repository = repository; 
    } 

    private T cachedObject; 
    public T Get() 
    { 
     if (cachedObject == null) 
     { 
      cachedObject = repository.Get(); 
     } 
     else 
     { 
      Console.WriteLine("Using cached repository to fetch '{0}'!", typeof(T).Name); 
     } 
     return cachedObject; 
    } 
} 

기본적으로, 내 응용 프로그램 IRepository<T> 사용하는 시간, 그것은 CachedRepository<T>의 인스턴스를 얻어야한다. 그러나 CachedRepository<T> 안에는 SqlRepository<T>의 실제 SQL 저장소를 가져와야합니다. Ninject에서 다음을 사용하여이 작업을 수행했습니다.

ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(SqlRepository<>)).WhenInjectedExactlyInto(tyepof(CachedRepository<>)); 
ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(CachedRepository<>)); 

Unity에서 어떻게 동일한 작업을 수행 할 수 있습니까? 나는 작동 제네릭이 아닌 저장소에 대한 버전이 있습니다

UnityContainer container = new UnityContainer(); 
container.RegisterType<IWidgetRepository, CachedWidgetRepository>(new InjectionMember[] { new InjectionConstructor(new SqlWidgetRepository()) }); 

을하지만 당신은 구문 오류없이 new SqlRepository<> 말할 수 없기 때문에이 구문은 일반 저장소와 전혀 작동하지 않습니다. 어떤 아이디어?

+0

관련 : https://stackoverflow.com/questions/9813630/how-to-do-open-generic-decorator-chaining-with-unity-unityautoregistration – Steven

답변

5

같이, 당신은 모든 개별 가능한 일반적인를 등록하지 않는 가정 :

container.RegisterType<IRepository<Things>, CachedRepository<Things>>(new InjectionMember[] {new InjectionConstructor(new SqlRepository<Things>())}); 

container.RegisterType<IRepository<OtherThings>, CachedRepository<OtherThings>>(new InjectionMember[] {new InjectionConstructor(new SqlRepository<OtherThings>())}); 

대신 말하는 단지 멋진 방법 사용자 정의 사출 공장, 사용할 수있는 "당신의 자신의 공장 함수를 작성 . "

// We will ask Unity to make one of these, so it has to resolve IRepository<Things> 
public class UsesThings 
{ 
    public readonly IRepository<Things> ThingsRepo; 

    public UsesThings(IRepository<Things> thingsRepo) 
    { 
     this.ThingsRepo = thingsRepo; 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     var container = new UnityContainer(); 

     // Define a custom injection factory. 
     // It uses reflection to create an object based on the requested generic type. 
     var cachedRepositoryFactory = new InjectionFactory((ctr, type, str) => 
      { 
       var genericType = type.GenericTypeArguments[0]; 
       var sqlRepoType = typeof (SqlRepository<>).MakeGenericType(genericType); 
       var sqlRepoInstance = Activator.CreateInstance(sqlRepoType); 
       var cachedRepoType = Activator.CreateInstance(type, sqlRepoInstance); 
       return cachedRepoType; 
      }); 

     // Register our fancy reflection-loving function for IRepository<> 
     container.RegisterType(typeof(IRepository<>), typeof(CachedRepository<>), new InjectionMember[] { cachedRepositoryFactory }); 

     // Now use Unity to resolve something 
     var usesThings = container.Resolve<UsesThings>(); 
     usesThings.ThingsRepo.Get(); // "Getting object of type 'Things'!" 
     usesThings.ThingsRepo.Get(); // "Using cached repository to fetch 'Things'!" 
    } 
} 
관련 문제