に対するジェネリック型を登録するのStructureMap:私は、次ているすべての可能な具体的な実装
:私は、コンテナ内の次のタイプを取得するように、私は> ICommandHandler <を登録するためにスキャンを使用したい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<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のタイプ。
二次的な目的は、コンテナではなく私のCommandDispatcherにICommandHandlers<ICommand>
のコレクションを注入できるかどうかです。しかし、今の構造では不可能だと思います。何か考えがあるなら間違っていることを証明してください。
EDITは - 私は私の一般的なインタフェースが実装非ジェネリックインターフェイスを追加し、私も抽象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を実行できますAddUser(AddUserHandlerのような)をサポートするMandHandlerですが、(AuditTrailHandlerのような)ICommandをサポートするハンドラも実行できます。
これは甘いです!
これは素晴らしいです! 私は以前にCanHandleメソッドを持っていましたが、StructureMapの魔法が私のためにできると思っていたので、それを削除しました。 私はもう少し行って抽象CommandHandlerを作成し、ジェネリックインターフェイスとコンクリートクラスの間に置いて、派生したすべてのクラスでそれを実装せずにCanHandleメソッドの恩恵を受けることができました。 恐ろしい、ありがとう! –