2010-11-21 3 views
2

두 가지 일반 매개 변수를 사용하여 제네릭 유형에 데코레이터를 등록하는 방법을 파악하려고합니다. 아래의 첫 번째 테스트 사례는 2- 매개 변수의 경우 예상대로 작동하지 않을 때 추가 한 1- 제네릭 매개 변수의 경우 위생 검사입니다.Castle Windsor 공개 일반 장식 자 유형 등록

1 제네릭 매개 변수 (이번에 반 변형이 있음)가있는 세 번째 (실패한) 사례는 Windsor가 공동 매개 변수와 반동식 제네릭 매개 변수를 다르게 취급한다는 것을 나타내므로 제 질문은 다음과 같습니다.

.NET 4.0을 사용하고 있습니다.

[Test] 
    public void RepoSingleGenericTest() 
    { 
     var windsorContainer = new Castle.Windsor.WindsorContainer(); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(IRepoSingle<>)) 
      .FromAssembly(typeof(StringRepoSingle).Assembly) 
      .If(t => typeof(CachingRepoSingle<>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(IRepoSingle<>))); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(IRepoSingle<>)) 
      .FromAssembly(typeof(BoolRepoSingle).Assembly) 
      .Unless(t => typeof(CachingRepoSingle<>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(IRepoSingle<>))); 

     var stringRepo = windsorContainer.Resolve<IRepoSingle<string>>(); 
     Assert.IsInstanceOf<StringRepoSingle>(stringRepo); 

     var boolRepo = windsorContainer.Resolve<IRepoSingle<bool>>(); 
     Assert.IsInstanceOf<BoolRepoSingle>(boolRepo); 
    } 

    [Test] 
    public void RepoDoublyGenericTest() 
    { 
     var windsorContainer = new Castle.Windsor.WindsorContainer(); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(IRepoDoublyGeneric<,>)) 
      .FromAssembly(typeof(StringRepoDoublyGeneric).Assembly) 
      .If(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>))); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(IRepoDoublyGeneric<,>)) 
      .FromAssembly(typeof(DateTimeRepoDoublyGeneric).Assembly) 
      .Unless(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>))); 

     var stringRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, string>>(); 
     Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, string>>(stringRepo); 

     var dateTimeRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, DateTime>>(); 
     Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, DateTime>>(dateTimeRepo); 
    } 

    [Test] 
    public void CommandTest() 
    { 
     var windsorContainer = new Castle.Windsor.WindsorContainer(); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(ICommand<>)) 
      .FromAssembly(typeof(GuidCommand).Assembly) 
      .If(t => typeof(DecoratorCommand<>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(ICommand<>))); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(ICommand<>)) 
      .FromAssembly(typeof(StringCommand).Assembly) 
      .Unless(t => typeof(DecoratorCommand<>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(ICommand<>))); 

     var stringComand = windsorContainer.Resolve<ICommand<string>>(); 
     Assert.IsInstanceOf<DecoratorCommand<string>>(stringComand); 

     var guidCommand = windsorContainer.Resolve<ICommand<Guid>>(); 
     Assert.IsInstanceOf<DecoratorCommand<Guid>>(guidCommand); 
    } 

    public interface IRepoSingle<out TValue> 
    { 
     TValue Get(); 
    } 

    public class StringRepoSingle : IRepoSingle<string> 
    { 
     public string Get() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class BoolRepoSingle : IRepoSingle<bool> 
    { 
     public bool Get() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class CachingRepoSingle<T> : IRepoSingle<T> 
    { 
     private readonly IRepoSingle<T> realRepo; 

     public CachingRepoSingle(IRepoSingle<T> realRepo) 
     { 
      if (realRepo == null) throw new ArgumentNullException("realRepo"); 

      this.realRepo = realRepo; 
     } 

     public T Get() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public interface IRepoDoublyGeneric<in TKey, out TValue> 
    { 
     TValue Get(TKey key); 
    } 

    public class StringRepoDoublyGeneric : IRepoDoublyGeneric<Guid, string> 
    { 
     public string Get(Guid key) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class DateTimeRepoDoublyGeneric : IRepoDoublyGeneric<Guid, DateTime> 
    { 
     public DateTime Get(Guid key) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class CachingRepoDoublyGeneric<TKey, TValue> : IRepoDoublyGeneric<TKey, TValue> 
    { 
     private readonly IRepoDoublyGeneric<TKey, TValue> realRepo; 

     public CachingRepoDoublyGeneric(IRepoDoublyGeneric<TKey, TValue> realRepo) 
     { 
      if (realRepo == null) throw new ArgumentNullException("realRepo"); 

      this.realRepo = realRepo; 
     } 

     public TValue Get(TKey key) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public interface ICommand<in T> 
    { 
     void Do(T t); 
    } 

    public class StringCommand : ICommand<string> 
    { 
     public void Do(string t) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class GuidCommand : ICommand<Guid> 
    { 
     public void Do(Guid t) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class DecoratorCommand<T> : ICommand<T> 
    { 
     private readonly ICommand<T> realComamnd; 

     public DecoratorCommand(ICommand<T> realComamnd) 
     { 
      if (realComamnd == null) throw new ArgumentNullException("realComamnd"); 

      this.realComamnd = realComamnd; 
     } 

     public void Do(T t) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

UPDATE : ... 다음은 트릭 않습니다,하지만 난이 가장 우아한 해결책이라고 생각 말할 수 없다 :

 [Test] 
    public void RepoDoublyGenericWithReflection() 
    { 
     var windsorContainer = new Castle.Windsor.WindsorContainer(); 

     // Register components for a caching decorator for all types implementing IRepoDoublyGeneric<,> - except for the generic cache itself 
     (from t in typeof (DateTimeRepoDoublyGeneric).Assembly.GetTypes() 
      let iRepo = t.GetInterfaces().SingleOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRepoDoublyGeneric<,>)) 
      where 
       t.IsClass && !t.IsAbstract && !typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t) 
       && iRepo != null 
      select iRepo) 
     .ForEach(rt => 
      windsorContainer.Register(Component.For(rt).ImplementedBy((typeof(CachingRepoDoublyGeneric<,>)).MakeGenericType(rt.GetGenericArguments()))) 
     ); 

     // Real repositories 
     windsorContainer.Register(
      AllTypes.Of(typeof(IRepoDoublyGeneric<,>)) 
      .FromAssembly(typeof(DateTimeRepoDoublyGeneric).Assembly) 
      .Unless(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t)) 
      .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>)) 
     ); 

     var stringRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, string>>(); 
     Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, string>>(stringRepo); 

     var dateTimeRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, DateTime>>(); 
     Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, DateTime>>(dateTimeRepo); 
    } 

이 르지의 제안에 따라, 나는 또한했습니다 시도 :

 [Test] 
    public void CommandTestUsingBasedOn() 
    { 
     var windsorContainer = new Castle.Windsor.WindsorContainer(); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(ICommand<>)) 
      .FromAssembly(typeof(GuidCommand).Assembly) 
      .If(t => typeof(DecoratorCommand<>).IsAssignableFrom(t)) 
      .BasedOn(typeof(ICommand<>)) 
      .WithService.Base()); 

     windsorContainer 
      .Register(AllTypes.Of(typeof(ICommand<>)) 
      .FromAssembly(typeof(StringCommand).Assembly) 
      .Unless(t => typeof(DecoratorCommand<>).IsAssignableFrom(t)) 
      .BasedOn(typeof(ICommand<>)) 
      .WithService.Base()); 

     var stringComand = windsorContainer.Resolve<ICommand<string>>(); 
     Assert.IsInstanceOf<DecoratorCommand<string>>(stringComand); 

     var guidCommand = windsorContainer.Resolve<ICommand<Guid>>(); 
     Assert.IsInstanceOf<DecoratorCommand<Guid>>(guidCommand); 
    } 
  • 하지만 그 동작을 변경하지 않습니다.

답변

4

AllTypes.BasedOn(typeof(typeof(ICommand<>))WithService.Base()으로 등록 할 때 작동합니까?

+0

안녕하세요. Krzysztof - 답장을 보내 주셔서 감사합니다 :) AllTypes (2.1.0.0 버전 사용)에 BasedOn이 없으므로 작동하는지 확인할 수 없습니다. 지금 당장 반사 기반 해결 방법이 있습니다 : –

+0

해결 방법에 대한 위의 게시물을 참조하십시오 ... –

+0

v2.1에서는 왜 안되나요? –

관련 문제