这是我的情景:
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"))
我无法正确注册Windsor。以下内容适用于所有非泛型命令:
container.Register(Classes.FromAssemblyNamed(namespaceName)
.BasedOn(typeof(IDomainCommandHandler<>))
.WithService.AllInterfaces()
.LifestyleTransient());
如果我直接注册每个可能的实现,它可以工作,但显然是次优的:
container.Register(
Component.For<IDomainCommandHandler<FakeGenericCommand<string, string>>>()
.UsingFactoryMethod(input => new FakeGenericCommandHandler<string, string>())
.LifestyleTransient());
建议?
答案 0 :(得分:1)
这里有一本教科书 - 需要typed factory的情况:我answered我在这里描述了如何使用它的问题
这个答案深受this article的启发。
注册所有处理程序
container.Register(Classes.FromAssemblyInThisApplication()
.BasedOn<IDomainCommandHandler>()
.WithServiceAllInterfaces());
声明一个工厂接口,它将返回命令的处理程序
public interface IDomainCommandHandlerFactory
{
IDomainCommandHandler[] GetHandlersForCommand(IDomainCommand command);
}
您需要将命令类型链接到处理程序,您可以使用自定义选择器进行处理:
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));
}
}
然后告诉Windsor你想要一个返回IDomainCommandHandler<T>
的工厂。不要为工厂编码任何东西。
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<HandlerSelector>());
container.Register(Component.For<IDomainCommandHandlerProvider>().AsFactory());
您现在可以使用工厂检索命令的处理程序
var provider = container.Resolve<IDomainCommandHandlerFactory>();
var msg = new Type2Message();
var msgHandler = provider.GetHandlersForCommand(msg.MessageType);
请注意,示例中的处理程序不是针对命令本身运行,而是具有Execute
函数。如果要返回已关闭的通用对象,则需要在解析后对其进行转换,因为无法从一种方法返回不同的类型。
我建议您阅读原始文章,因为它还包含有关生活方式,组件发布和其他有趣观点的其他信息。
这里是我用于请求的选择器示例,其中我将请求和响应指定为通用组件
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是响应)
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 });