我正在尝试使用Castle Windsor解决具有约束的混合开闭通用类型.如果Foo实现了IFoo<> ;,这应该能够解析所有开放的泛型: container.Register(Component.For(typeof(IFoo)).ImplementedBy(typeof(Foo)))); 我的情况稍微复杂一些: 我有以下Handler类:
public abstract class CommandHandlerBase<TCommand,TResponse>
: IRequestHandler<TCommand,TResponse>
where TCommand : IRequest<TResponse>
{
public abstract Task<TResponse> Handle(
TCommand request,CancellationToken cancellationToken);
}
public class AddMasterDataEntityCommandHandler<TNewEntityData>
: IRequestHandler<TNewEntityData,Response>
where TNewEntityData : IRequest<Response>
{
public Task<Response> Handle(
TNewEntityData request,CancellationToken cancellationToken)
{
// ...
}
}
这个想法是AddMasterDataEntityCommandHandler将是一个通用命令处理程序,可以处理TNewEntityData类型的任何类型的合同.
由于我使用的是Mediatr,因此我的合同必须实现IRequest<,>.在这种情况下,我强制所有处理程序都应返回一个Response.
用法示例:
响应响应=等待mediator.Send(new AddMasterDataEntityCommand< NewPlace>());
我创建了一个简单的控制台应用程序来隔离此行为:
public static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Types.FromThisAssembly()
.BasedOn(typeof(IRequestHandler<,>))
.Unless(t => t.IsAbstract || t.IsInterface)
.WithServices(typeof(IRequestHandler<,>))
.LifestyleTransient());
var instance = container.Resolve(typeof(IRequestHandler<NewData,Response>));
}
Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException: ‘Types ConsoleApp4.NewData,ConsoleApp4.Response don’t satisfy generic constraints of implementation type ConsoleApp4.AddMasterDataEntityCommandHandler’1 of component ‘ConsoleApp4.AddMasterDataEntityCommandHandler’1′. This is most likely a bug in your code.’
我在这里看不到问题,CW应该能够解决打开/关闭的泛型,对吗?此外,该问题似乎与其他响应参数(TResponse类型)有关.我是否以错误的方式注册了组件?我相信我不会搞乱通用约束…
在此先感谢任何可以看一下的人.
我最初使用IGenericImplementationMatchingStrategy尝试了一个实现,但仅能使用一个泛型处理一个类型,却无法使其正常工作.我最终用了一些反射魔术来像这样注册:
private void RegisterGenericMasterDataCommandHandlers(IWindsorContainer container) {
foreach (Type contractType in contractTypes) {
Type requestedType = typeof(IRequestHandler<,>).MakeGenericType(typeof(AddMasterDataEntityCommand<>).MakeGenericType(contractType),typeof(Response));
Type implementedType = typeof(AddMasterDataEntityCommandHandler<>).MakeGenericType(contractType);
container.Register(Component.For(requestedType,implementedType));
}
}