我有以下几点:StructureMap对所有可能的具体实现注册泛型类型
public interface ICommand { }
public class AddUser : ICommand
{
public string Name { get; set; }
public string Password { get; set; }
}
public interface ICommandHandler<T> : IHandler<T> where T : ICommand
{
void Execute(T command);
}
public class AddUserHandler : ICommandHandler<AddUser>
{
public void Execute(AddUser command)
{
Console.WriteLine("{0}: User added: {1}", GetType().Name, command.Name);
}
}
public class AuditTrailHandler : ICommandHandler<ICommand>
{
public void Execute(ICommand command)
{
Console.WriteLine("{0}: Have seen a command of type {1}", GetType().Name, command.GetType().Name);
}
}
我想用扫描注册ICommandHandler <>让我得到以下类型的容器:
ICommandHandler<AddUser>
与具体类型AddUserHandler
ICommandHandler<AddUser>
与具体类型
我已经试过这与IRegistrationConvention的实施,并在一个点上,我有它的工作,但我不能让我的脑袋周围如何做到这一点。
我们的目标是能够执行多个处理程序特定的ICommand实现像这样:
// A method in CommandDispatcher
public void SendCommand<T>(T command) where T : ICommand {
var commandHandlers = container.GetAllInstances<ICommandHandler<T>>();
foreach (var commandHandler in commandHandlers) {
commandHandler.Execute(command);
}
}
我想AuditTrailHandler<ICommand>
执行的ICommand的所有具体实现,因此需要将它们注册为所有ICommand类型。
次要目标是如果我可以将一个ICommandHandlers<ICommand>
集合注入到我的CommandDispatcher而不是容器中,但我认为这对我现在的结构是不可能的。如果你有任何想法,证明我错了。
编辑 - 解决
我添加了一个非通用接口,我的通用接口实现,然后我还添加了一个抽象CommandHandler<T>
所以我没有实现CanHandle或执行(对象)的所有方法我的处理程序。
这是工作结构:
public interface ICommandHandler
{
void Execute(object command);
bool CanHandle(ICommand command);
}
public interface ICommandHandler<T> : ICommandHandler, IHandler<T> where T : ICommand
{
void Execute(T command);
}
public abstract class AbstractCommandHandler<T> : ICommandHandler<T> where T : ICommand
{
public abstract void Execute(T command);
public void Execute(object command)
{
Execute((T)command);
}
public virtual bool CanHandle(ICommand command)
{
return command is T;
}
}
而且因为这原本是一个StructureMap的问题,这里是扫描到补充一点:
Scan(x =>
{
x.AssemblyContainingType<MyConcreteHandler>();
x.IncludeNamespaceContainingType<MyConcreteHandler>();
x.AddAllTypesOf<ICommandHandler>();
x.WithDefaultConventions();
});
这使我能够在注入一个IEnumerable我的CommandDispatcher并执行如下:
public void SendCommand<T>(T command) where T : ICommand
{
var commandHandlersThatCanHandle = commandHandlers.Where(c => c.CanHandle(command));
foreach (var commandHandler in commandHandlersThatCanHandle)
{
commandHandler.Execute(command);
}
}
这使我能够执行Com MandHandlers支持AddUser(就像AddUserHandler),但我也能够执行支持ICommand的处理程序(如AuditTrailHandler)。
这很甜!
太棒了! 我以前有过CanHandle方法,但是因为我认为StructureMap魔术可以帮我做到这一点,所以将其删除。 我甚至进一步做了一个抽象的CommandHandler,并将它放在泛型接口和具体类之间,这样我就可以从CanHandle方法中受益,而无需在所有派生类中实现它。 真棒,谢谢! –
2011-01-19 16:11:59