我有以下幾點: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