autofac解析所有ICommandHandler <icommand,imessageresult> </icommand,imessageresult>

时间:2015-03-10 16:38:45

标签: c# autofac

您好。在.Net的MessageDispatch场景中,我注册了所有我的命令处理程序:

builder.RegisterAssemblyTypes(commandsAssemblies)
.AsClosedTypesOf(typeof(ICommandHandler<,>))
.InstancePerRequest();

在我的messageDispatcher的OnActivating方法中,我想用这样的messageDispatcher注册commandHandlers。

builder.RegisterType<MessageDispatcher>()
.As<IMessageDispatcher>().InstancePerRequest()
.OnActivating(e =>

{
 var handlers = e.Context.Resolve(IEnumerable<ICommandHandler<ICommand,IMessageResult>>);
    foreach (var handler in handlers)
    {
        e.Instance.RegisterCommandHandler(handler);
    }
......

commandHandler的实现方式如下:

public class ActivateCampaignHandler : CommandHandler<ActivateCampaign,MessageResult>   
{
    ....

我的问题是Resolve不起作用。我可以看到处理程序已注册,但只有2个服务自己和ICommandHandler

如何解决所有命令处理程序?

1 个答案:

答案 0 :(得分:1)

我可以看到3个解决方案来检索IEnumerable<ICommandHandler<,>>

最简单的方法是引入非通用ICommandHandler接口:

    public interface ICommandHandler { }
    public interface ICommandHandler<TCommand, TMessageResult>
        : ICommandHandler
        where TCommand : ICommand
        where TMessageResult : IMessageResult
    { }

    // register it this way 
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .AsClosedTypesOf(typeof(ICommandHandler<,>))
            .As<ICommandHandler>();

这是我推荐的解决方案,因为使用非通用接口可能更容易。

第二个解决方案包括使您的界面协变(使用out修饰符)以允许从TestCommandHandler投射到ICommandHandler<ICommand, IMessageResult>并将您的类型注册为ICommandHandler<ICommand, IMessageResult>

    public interface ICommandHandler<out TCommand, out TMessageResult>
        where TCommand : ICommand
        where TMessageResult : IMessageResult
    { }

    // register this way
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .AsClosedTypesOf(typeof(ICommandHandler<,>))
            .As<ICommandHandler<ICommand, IMessageResult>>();

    // resolve this ways
    var commandHandlers = container.Resolve<IEnumerable<ICommandHandler<ICommand, IMessageResult>>>();
    Console.WriteLine(commandHandlers.Count());

最新的解决方案是创建自己的IRegistrationSource它需要更多的工作,但它会避免将您的类型注册为ICommandHandler<ICommand, IMessageResult>,并允许您解决ICommandHandler<ISpecificCommand, IMessageResult>之类的问题(如果你IRegistrationSource实现允许这样做。

您可以查看ContravariantRegistrationSource以了解如何制作自己的内容。