autofac resolve all ICommandHandler<ICommand,IMessageResult>

。_饼干妹妹 提交于 2020-03-26 08:39:07

问题


Hi In a MessageDispatch Scenario in .Net i register all my command handlers like this:

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

in my OnActivating method for my messageDispatcher i want to register the commandHandlers with the messageDispatcher like this.

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

A commandHandler is implemented like:

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

My problem is that the Resolve doesnt work. I Can se that the handler is registered, but only has 2 services it self and ICommandHandler

How do I resolve all my commandhandlers?


回答1:


I can see 3 solutions to retrieve a IEnumerable<ICommandHandler<,>>.

The easiest one would be to introduce a non generic ICommandHandler interface :

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

This is the solution I recommend because it may be easier to work with a non generic interface.

The second solution would consist of making your interface covariant (using the out modifier) to allow casting from TestCommandHandler to ICommandHandler<ICommand, IMessageResult> and register your types as 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());

The latest solution would be to create your own IRegistrationSource it requires more work but it will avoid registering your types as ICommandHandler<ICommand, IMessageResult> and will allow you to resolve things like that ICommandHandler<ISpecificCommand, IMessageResult> (if you IRegistrationSource implementation allows that of course).

You can have a look at the ContravariantRegistrationSource to see how to make yours.



来源:https://stackoverflow.com/questions/28969289/autofac-resolve-all-icommandhandlericommand-imessageresult

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!