使用 Castle Windsor 解决混合开闭泛型问题

Resolving mixed open-closed generics with Castle Windsor

我正在尝试使用 Castle Windsor 解决具有约束的混合开闭泛型类型。如果 Foo 实现 IFoo<>:

,这应该能够解决任何开放的泛型

container.Register(Component.For(typeof(IFoo<>).ImplementedBy(typeof(Foo<>)));

我的情况稍微复杂一点:

我有以下 Handler class:

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<,>,他们确实这样做了。在这种情况下,我强制所有处理程序应该 return a Response.

用法示例:

Response response = await 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 应该能够解析 open/closed 泛型,对吧?此外,该问题似乎与作为 TResponse 类型的附加 Response 参数有关。我是否以错误的方式注册了组件?我相信我没有搞砸通用约束...

提前感谢任何可以看一看的人。

Krzysztof Kozmic 带领我走向了正确的方向:

我最初尝试使用 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));
    }
}