O StructureMap registra tipos genéricos em todas as implementações concretas possíveis

Eu tenho o seguinte:

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);
    }
}

Eu gostaria de usar a varredura para registrar o ICommandHandler <> para obter os seguintes tipos no contêiner:

ICommandHandler<AddUser> com tipo de concretoAddUserHandlerICommandHandler<AddUser> com tipo de concretoAuditTrailHandler

Eu tentei isso com uma implementação do IRegistrationConvention e, a certa altura, ele funcionava, mas simplesmente não consigo entender como o fiz.

O objetivo é poder executar vários manipuladores para uma implementação específica do ICommand, como:

// 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);    
   }
}

eu quero oAuditTrailHandler<ICommand> executar para todas as implementações concretas do ICommand, daí a necessidade de registrá-las para todos os tipos de ICommand.

O objetivo secundário seria se eu pudesse injetar uma coleção deICommandHandlers<ICommand> no meu CommandDispatcher em vez do contêiner, mas acho que é impossível com a estrutura que tenho agora. Prove que estou errado, se você tem alguma idéia.

EDIT - resolvido

Eu adicionei uma interface não genérica que minha interface genérica implementa e também adicionei um resumoCommandHandler<T> portanto, não tenho que implementar os métodos CanHandle ou Execute (object) em todos os meus manipuladores.

Esta é a estrutura de trabalho:

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;
    }
}

E como essa era originalmente uma pergunta do StructureMap, aqui está a verificação para adicionar isso:

Scan(x =>
        {
            x.AssemblyContainingType<MyConcreteHandler>();
            x.IncludeNamespaceContainingType<MyConcreteHandler>();
            x.AddAllTypesOf<ICommandHandler>();
            x.WithDefaultConventions();
        });

Isso me permite injetar um IEnumerable no meu CommandDispatcher e executar da seguinte maneira:

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);    
        }
    }

Isso me permite executar CommandHandlers que oferecem suporte ao AddUser (como o AddUserHandler), mas também posso executar um manipulador que suporte o ICommand (como o AuditTrailHandler).

Isto é doce!

questionAnswers(1)

yourAnswerToTheQuestion