通用命令/命令处理程序的Windsor注册 [英] Windsor registration for generic commands/command handlers

查看:57
本文介绍了通用命令/命令处理程序的Windsor注册的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的情况:

public static class DomainCommandProcessor
{
    public static void Dispatch<T>(T command) where T : IDomainCommand
    {
        var serviceLocator = ServiceLocator.Current;

        var handler = serviceLocator.GetInstance<IDomainCommandHandler<T>>();
        if (handler != null)
            handler.Handle(command);
    }
}

public class FakeGenericCommand<T1, T2> : IDomainCommand
{
    public FakeGenericCommand(T1 first, T2 second)
    {
        First = first;
        Second = second;
    }

    public T1 First { get; private set; }
    public T2 Second { get; private set; }
}

public class FakeGenericCommandHandler<T1, T2> : IDomainCommandHandler<FakeGenericCommand<T1, T2>>
{
    public void Handle(FakeGenericCommand<T1, T2> command)
    {
        // something interesting
    }
}

用法:

DomainCommandProcessor.Dispatch(new FakeGenericCommand<string, string>("hi", "there"))

I无法获得温莎的注册权。以下代码非常适合我所有的非通用命令:

I can't get the Windsor registration right. The following works great for all of my non-generic commands:

container.Register(Classes.FromAssemblyNamed(namespaceName)
    .BasedOn(typeof(IDomainCommandHandler<>))
    .WithService.AllInterfaces()
    .LifestyleTransient());

如果我直接注册每个可能的实现,它都可以工作,但显然不是最佳选择:

If I register each possible implementation directly, it works but is obviously sub-optimal:

container.Register(
    Component.For<IDomainCommandHandler<FakeGenericCommand<string, string>>>()
        .UsingFactoryMethod(input => new FakeGenericCommandHandler<string, string>())
        .LifestyleTransient());

建议?

推荐答案

这里提供的是一个需要键入工厂:我回答一个问题,我在其中描述了如何使用它

What you have here is a textbook-case of needing a typed factory: I answered a question where I described how to use it

此答案很大程度上受本文

注册所有处理程序

container.Register(Classes.FromAssemblyInThisApplication()
    .BasedOn<IDomainCommandHandler>()
    .WithServiceAllInterfaces());

声明一个工厂接口,该接口将返回命令的处理程序

Declare a factory interface that will return the handlers for a command

public interface IDomainCommandHandlerFactory
{
    IDomainCommandHandler[] GetHandlersForCommand(IDomainCommand command);
}

您需要将命令类型链接到处理程序,您可以使用一个自定义选择器:

You need to link your command types to the handlers, which you can do with a custom selector:

public class HandlerSelector:ITypedFactoryComponentSelector
{
    public TypedFactoryComponent SelectComponent(MethodInfo method, Type type, object[] arguments)
    {
        var message = arguments[0];
        var handlerType = typeof(IDomainCommandHandler<>).MakeGenericType(message.GetType());
        return new TypedFactoryComponentCollection(handlerType.MakeArrayType(), new Arguments(arguments));
    }
}

然后告诉温莎您想让一家工厂返回 IDomainCommandHandler< T> 。不要为工厂编写任何代码。

Then tell Windsor you want a factory that will return a IDomainCommandHandler<T>. Don't code anything for the factory.

container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<HandlerSelector>());
container.Register(Component.For<IDomainCommandHandlerProvider>().AsFactory());

您现在可以使用工厂检索命令的处理程序

You can now use the factory to retrieve your handlers for a command

var provider = container.Resolve<IDomainCommandHandlerFactory>();
var msg = new Type2Message();
var msgHandler = provider.GetHandlersForCommand(msg.MessageType);






请注意,示例中的处理程序不是针对命令本身运行,但具有 Execute 函数。如果您想返回封闭的通用对象,则需要在解析后进行转换,因为您不能从一种方法返回不同的类型。


Please note that the handlers in the example are not running against the command itself but have a Execute function. If you want to return closed generic objects you need to cast them after resolution since you cannot return different types from one method.

我建议您阅读原始文章,因为它还包含有关生活方式,组件释放和其他有趣点的其他信息。

I'd advise you reading the original article since it also contains additional information regarding lifestyle, releasing of components and other interesting points.

这里是我使用的选择器的一个示例对于我将请求和响应指定为通用组件的请求

Here an example of the Selector I use for requests where I specify the request and the response as generic components

protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
    var request = arguments[0].GetType();
    var response = arguments[1] as Type;
    var handlerType = typeof(IHandlerOf<,>).MakeGenericType(request, response);
    return handlerType;
}

这是工厂致电的结果(T是请求,R响应)

And here is the result of the call to the factory (T is the request, R the response)

var handler = handlerFactory.GetHandler<T>(input, typeof(R));
var requestType = input.GetType();
var responseType = typeof(R);
var handlerType = typeof(IHandlerOf<,>).MakeGenericType(requestType, responseType);
r = (R)handlerType.GetMethod("Handle").Invoke(handler, new object[] { input });

这篇关于通用命令/命令处理程序的Windsor注册的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆