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);
}
- 하지만 그 동작을 변경하지 않습니다.
안녕하세요. Krzysztof - 답장을 보내 주셔서 감사합니다 :) AllTypes (2.1.0.0 버전 사용)에 BasedOn이 없으므로 작동하는지 확인할 수 없습니다. 지금 당장 반사 기반 해결 방법이 있습니다 : –
해결 방법에 대한 위의 게시물을 참조하십시오 ... –
v2.1에서는 왜 안되나요? –