问题
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