I got an assembly with many concrete types that implement IHandler<TCommand>, such as the following:
public class MoveCustomerHandler : IHandler<MoveCustomerCommand>
{
void IHandler<MoveCustomerCommand>.Handle(MoveCustomerCommand c)
{
// some business logic for moving a customer.
}
}
Currently, I'm registering them one by one as follows:
builder.RegisterType<MoveCustomerHandler>()
.As<IHandler<MoveCustomerCommand>>();
builder.RegisterType<ProcessOrderHandler>()
.As<IHandler<ProcessOrderCommand>>();
builder.RegisterType<SomeOtherFancyHandler>()
.As<IHandler<SomeOtherFancyCommand>>();
// Many handler registrations here...
The command handlers are injected using constructor injection, as can be seen below:
public class OrderController
{
private readonly IHandler<ProcessOrderCommand> handler;
public OrderController(IHandler<ProcessOrderCommand> handler)
{
this.handler = handler;
}
}
Is there a way to batch register all my handlers in an easy way using Autofac?
In a similar style to Jim's answer but taking advantage of AsClosedTypesOf:
Assembly[] assemblies = GetYourAssemblies();
builder.RegisterAssemblyTypes(assemblies)
.AsClosedTypesOf(typeof(IHandler<>));
You probably want something like this, although I'm not sure how IsAssignable() behaves with open generics.
Assembly[] assemblies = GetYourAssemblies();
builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.IsAssignableFrom(typeof(IHandler<>)))
.AsSelf()
.AsImplementedInterfaces();
Related
I use a MediatR library in my Asp .Net core 6 app. And I have a the same logic for a group of requests, so I want to use the same handler for all of them. The problem is not new, but the solutions that I found did not help me. I have my own solution to solve this problem, but I do not like it and hope somebody knows a better way to solve this problem.
The example is shown here:
public class HandlerRequest<T> : IRequest
{
public T Data { get; set; }
}
public class Handler<T> : IRequestHandler<HandlerRequest<T>>
{
public Task<Unit> Handle(HandlerRequest<T> request, CancellationToken cancellationToken)
{
// the logic is here
return Task.FromResult(new Unit());
}
}
The registration of MediatR is as follows:
builder.Services.AddMediatR(typeof(BusinessLayer));
When I try to call my mediatr for example:
await _mediator.Send(new HandlerRequest<int>{Data = 5});
await _mediator.Send(new HandlerRequest<string>{Data = "TEST"});
I get an exception:
Error constructing handler for request of type
MediatR.IRequestHandler2[AT.Messenger.Credentials.Business.Requests.V1.Modeles.HandlerRequest1[System.Int32],MediatR.Unit].
Register your handlers with the container. See the samples in GitHub
for examples.
The problem happens because MediatR can not register generic handler. I also tried to register handler as scoped or singleton service as I've seen that advice on the internet, but it does not help.
The only solution that I found - is inherit a new class from my handler:
public class HandlerInt : Handler<int>
{
}
public class HandlerString : Handler<string>
{
}
If use this approach, all works, but I don't like this solution. If anybody know better way to solve this problem give me an advice please.
You have the following options, first, register what you will need explicitly like this.
services.AddTransient<IRequestHandler<HandlerRequest<int>, Unit>>, Handler<int>>();
//so on and so forth
This way you have registered the handlers for known types.
If you have open-bound generic, you can look into my PR that gives you a
services.RegisterGenericMediatRHandlers(typeof(GenericHandlerBase).Assembly);
to automatically register classes inheriting from the constrained interface by using the method provided above.
Lastly, you can opt to use Autofac and register all your handlers like this:
var mediatrOpenTypes = new[]
{
typeof(IRequestHandler<,>),
typeof(IRequestExceptionHandler<,,>),
typeof(IRequestExceptionAction<,>),
typeof(INotificationHandler<>),
};
foreach (var mediatrOpenType in mediatrOpenTypes)
{
builder
.RegisterAssemblyTypes(_assemblies.ToArray())
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();
}
//also by simply
//builder.RegisterGeneric(typeof(Handler<>)).AsImplementedInterfaces();
This will also register all the generic handlers and you won't even have to register it explicitly inside the DI.
btw
The method you used to handle generic registration is the way described in the docs, to quote
If you have an open generic not listed above, you'll need to register it explicitly. For example, if you have an open generic request handler, register the open generic types explicitly:
services.AddTransient(typeof(IRequestHandler<,>), typeof(GenericHandlerBase<,>));
This won't work with generic constraints, so you're better off creating an abstract base class and concrete closed generic classes that fill in the right types.
Source: docs link
I have colleted a lot of information and figured out a solution to register any kind of generic Mediator Handlers.
I was stuck trying to register one generic implementation with another generic class inside INotificationHandler, like this:
public class DomainEventsDispatcher<TEvent> : INotificationHandler<DomainEventDispatch<TEvent>> where TEvent : DomainEvent
PS: I'll use the example above to explain below.
Obviously, your cannot simply use "services.AddMediatr(typeof(AppAssembly))" because using Mediator with generic types, Handlers are not loaded into DI on startup.
So, I decided to register each implementation of each type of TEvent, however, I did it by looping the assemblies that implemented TEvent type and building each part to be used on services.AddTransient.
Looking for assemblies that implemented TEvent type;
First variable: Build the generic used inside INotificationHandler;
Second variable: Build the INotificationHandler with first variable;
Third variable: Build the generic implementation with TEvent type;
Returing the list ready to be injected;
Here is an extension I did to loop and build necessary types to register on DI:
public static class AssemblyExtensions
{
public static List<(Type notificationHandler, Type implementation)> GetGenericNotificationHandlerForTypesOf(this Assembly assembly,
Type AbstractClassToFilter, Type GenericUsedWithNotificationHandler, Type ImplementationType, Type NotificationHandlerGeneric)
{
List<(Type, Type)> list = new List<(Type, Type)>();
foreach (Type item in from t in assembly.GetTypes()
where !t.IsAbstract && !t.IsInterface && t.BaseType == AbstractClassToFilter
select t)
{
var genericForNotificationHandler = GenericUsedWithNotificationHandler.MakeGenericType(item);
var notificationHandler = NotificationHandlerGeneric.MakeGenericType(genericForNotificationHandler);
var implementation = ImplementationType.MakeGenericType(item);
list.Add((notificationHandler, implementation));
}
return list;
}
}
Here is how to use (please take a look in the first example to understand the code below):
var registerPairs = typeof(DomainEvent).Assembly.GetGenericNotificationHandlerForTypesOf(typeof(DomainEvent), typeof(DomainEventDispatch<>), typeof(DomainEventsDispatcher<>), typeof(INotificationHandler<>));
registerPairs.ForEach(pair => services.AddTransient(pair.notificationHandler, pair.implementation));
Was unsure how to make a sensible title for this post.
Say I have a class
[Export(typeof(IMessageSender))]
public class MessageSender : IMessageSender
{
private IMessagingInterface _messagingInterface;
private IEventAggregator _eventAggregator;
[ImportingConstructor]
public MessageSender(IMessagingInterface messagingInterface, IEventAggregator eventAggregator)
{
_messagingInterface = messagingInterface;
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
_messagingInterface.Write(message);
}
public InterfaceStatus GetStatus()
{
return _messagingInterface.Status;
}
...
etc. Many methods in this class.
}
and I have several different IMessagingInterface, such as
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
In my application, I currently instantiate the different parts like this at the startup of my application:
eventAggregator = new EventAggregator();
batch.AddExportedValue<IMessageSender>("SerialPortSender", new MessageSender(new SerialPortInterface(), eventAggregator);
batch.AddExportedValue<IMessageSender>("UdpSender", new MessageSender(new UdpInterface (), eventAggregator);
...
etc for the rest
Then I can specify which one I want injected elsewhere by using the contract name.
However, I feel like doing this composition myself in the bootstrapper and creating instances with new is wrong and unnecessary, but I haven't found a way to do it differently.
Have a look at this post:
Getting all types that implement an interface
And then use Activator.CreateInstance(...) to construct the instances (see: https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
Something like this should do it:
eventAggregator = new EventAggregator();
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach (var t in types)
{
var instance = (IMyInteface)Activator.CreateInstance(t);
batch.AddExportedValue<IMessageSender>(t.Name, new MessageSender(instance, eventAggregator);
}
As Tchi Yuan pointed out, using a IOC framework is also an option such as:
Unity
Ninject
These will handle the scanning of assemblies and instance creation for you according to the configurations you provide.
I've had this problem in the past and what I did is that I used Microsoft Unity in conjuncture with MEF and then simply pass your unity container to your MEF extension/plugin constructor. Registering and resolving named dependencies with Unity is trivial.
I have a project that is using a decorator convention to wrap command handlers with logging decorators via interception of open generic types in StructureMap 2.6. However, I'm having difficulty figuring out the best way to implement the equivalent functionality in StructureMap 3 so that I can complete the upgrade.
Here's the code from StructureMap 2.6. First, in my IoC class I have a scanning policy set up to resolve the command handlers:
scan.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
Next, I have a decorator convention, which is added to the IoC's scanning conventions, that wires up the decorator interception:
public class CommandLoggingDecoratorConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
var interfaceTypes = type.GetInterfaces();
foreach (var interfaceType in interfaceTypes)
{
if (interfaceType.IsGenericType
&& interfaceType.GetGenericTypeDefinition() == typeof(ICommandHandler<>))
{
var arguments = interfaceType.GetGenericArguments();
var closedType = typeof(CommandHandlerLoggingDecorator<>)
.MakeGenericType(arguments);
registry.For(interfaceType)
.EnrichWith((c, p) => Activator.CreateInstance(
closedType,
p,
c.GetInstance<IMessageLoggingHelper>(),
c.GetInstance<ILog>()));
}
}
}
}
Then, we have a command bus which maps a specific command to a command handler and calls the Execute method on the logging decorator (which is wrapping the command handler) which in turns calls the Execute method on the command inside of the decorator:
public class CommandBus : ICommandBus
{
public static IContainer Container;
public void Execute(ICommand command)
{
var handlerType = typeof (ICommandHandler<>)
.MakeGenericType(command.GetType());
dynamic handler = Container
.GetAllInstances(handlerType)
.Cast<dynamic>()
.Single();
handler.Execute((dynamic) command);
}
}
I have been able to make this work in StructureMap 3 by replacing my decorator convention with an interceptor policy and adding the interceptor policy in the IoC class.
Here's the interceptor policy:
public class CommandLoggingDecoratorPolicy : IInterceptorPolicy
{
public string Description { get; private set; }
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (pluginType == typeof (ICommandHandler<>))
yield return new DecoratorInterceptor(
typeof(ICommandHandler<>),
typeof(CommandHandlerLoggingDecorator<>));
}
And here's the code that adds it to the IoC's interceptor policies:
x.Policies.Interceptors(new CommandLoggingDecoratorPolicy());
However, when I call Container.GetInstance (in my CommandBus) it returns the matching Command Handler implementation instead of the Command Logging decorator. If I call Container.GetAllInstances, it returns both the implementation (first) and the decorator (second).
So, right now, the only way I am able to make this work is if I either explicitly choose the second item returned from Container.GetAllInstances or filter the results and choose the decorator using reflection. Here's an example:
public class CommandBus : ICommandBus
{
public static IContainer Container;
public void Execute(ICommand command)
{
var handlerType = typeof (ICommandHandler<>)
.MakeGenericType(command.GetType());
var handlers = Container
.GetAllInstances(handlerType)
.Cast<dynamic>();
var handler = handlers.ToList()[1];
handler.Execute((dynamic) command);
}
}
However, this seems like a pretty ugly solution. There clearly must be something that I'm missing. First, why is Container.GetInstance returning the implementation rather than the decorator when I've explicitly added a decorator interception policy? Second, is there a better way that I should be doing this altogether?
Any ideas or suggestions would be greatly appreciated!
See this remarkably similar sample (that I just wrote) in the StructureMap codebase for an example of using decorators with generic types: https://github.com/structuremap/structuremap/blob/b405d8f752b45ac250f057d9e3de8554f2a7f40f/src/StructureMap.Testing/Bugs/OpenGenericDecorator_question.cs
I seem to be doing this a fair bit in my code:
public class ActionsModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.Register(c => LogManager.GetCurrentClassLogger()).As<ILog>().InstancePerDependency();
// Autofac doesn't seem to be able to inject things without explicit binding
builder.RegisterType<ComboActions>().As<ComboActions>().InstancePerHttpRequest();
builder.RegisterType<AppActions>().As<AppActions>().InstancePerHttpRequest();
}
}
}
Where the 'actions' class is a class I require to be injected into my controller, and has various other sub-dependencies.
Seems a bit rubbish. Why can't autofac resolve that the class has a constructor with dependencies that are already satisfied and manufacture an instance automatically?
I mean, if class A requires class B to be injected and class B requires C, D, E, etc. fair enough, I guess you dont want to walk the entire dependency chain to see if you can make a class at run time. ...but if class A directly depends on C and D which are explicitly bound, surely that's a trivial case?
Am I missing something? Can't seem to see any documentation for this...
You don't have to register every type. Autofac provides a AnyConcreteTypeNotAlreadyRegisteredSource that will automatically grab a concrete type if you haven't already provided a registration.
For example:
var builder = new ContainerBuilder();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
...
var myConcreteType = container.Resolve<MyConcreteType>();
The sources allow more complex things, like automatically injecting mocked objects for interfaces and abstract class based dependencies.
AFAIK, Autofac requires every needed type to be registered in the container, but this does not mean you have to do each one individually. Almost 99% of my registrations are handled by adding this attribute to the type:
[AttributeUsage(AttributeTargets.Class)]
public class AutoRegisterAttribute : Attribute { }
So for example, you'd have
[AutoRegister]
class ComboActions
{
And then I register them with this:
public class AutoScanModule : Module
{
private readonly Assembly[] _assembliesToScan;
public AutoScanModule(params Assembly[] assembliesToScan)
{
_assembliesToScan = assembliesToScan;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(_assembliesToScan)
.Where(t => t.GetCustomAttributes(typeof (AutoRegisterAttribute), false).Any())
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
}
Like I said, this covers most of my registrations and then I usually only have to worry about things like 3rd party types, open generics and decorators.
EDIT: Check out the reply from Kaleb that proves me wrong. Cool feature I never knew about!
I was triggered by this SO question about (.NET 4.0) covariance and contravariance support for Autofac, and now I'm trying to achieve something similar, but without any luck.
What I am trying to achieve is configure Autofac in such way that when I resolve a single concrete IEventHandler<TEvent> (for the sake of demonstration using container.Resolve, but normally of course using constructor injection), Autofac will return me a MultipleDispatchEventHandler<TEvent> that wraps all registered event handlers that are assignable from the requested handler.
In other words, when I write this:
var handler = container
.GetInstance<IEventHandler<CustomerMovedEvent>>();
handler.Handle(new CustomerMovedEvent());
With respect to the application design (given below), I'd expect a MultipleDispatchEventHandler<CustomerMovedEvent> to be returned that wraps both a CustomerMovedEventHandler and a NotifyStaffWhenCustomerMovedEventHandler.
Here is the application design:
// Events:
public class CustomerMovedEvent { }
public class CustomerMovedAbroadEvent : CustomerMovedEvent { }
public class SpecialCustomerMovedEvent : CustomerMovedEvent { }
// Event handler definition (note the 'in' keyword):
public interface IEventHandler<in TEvent>
{
void Handle(TEvent e);
}
// Event handler implementations:
public class CustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public void Handle(CustomerMovedEvent e) { ... }
}
public class NotifyStaffWhenCustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public void Handle(CustomerMovedEvent e) { ... }
}
public class CustomerMovedAbroadEventHandler
: IEventHandler<CustomerMovedAbroadEvent>
{
public void Handle(CustomerMovedAbroadEvent e) { ... }
}
This is the definition of the MultipleDispatchEventHandler<TEvent>, defined in the Composition Root:
// A composite wrapping possibly multiple handlers.
public class MultipleDispatchEventHandler<TEvent>
: IEventHandler<TEvent>
{
private IEnumerable<IEventHandler<TEvent>> handlers;
public MultipleDispatchEventHandler(
IEnumerable<IEventHandler<TEvent>> handlers)
{
this.handlers = handlers;
}
public void Handle(TEvent e)
{
this.handlers.ToList().ForEach(h => h.Handle(e));
}
}
This is my current configuration:
var builder = new ContainerBuilder();
// Note the use of the ContravariantRegistrationSource (which is
// available in the latest release of Autofac).
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IEventHandler<>).Assembly)
.AsClosedTypesOf(typeof(IEventHandler<>));
// UPDATE: I'm registering this last as Kramer suggests.
builder.RegisterGeneric(typeof(MultipleDispatchEventHandler<>))
.As(typeof(IEventHandler<>)).SingleInstance();
var container = builder.Build();
With the current configuration, the application fails during the call to Resolve, with the following exception:
Autofac.Core.DependencyResolutionException: Circular component
dependency detected:
MultipleDispatchEventHandler'1[[SpecialCustomerMovedEvent]] ->
IEventHandler'1[[SpecialCustomerMovedEvent]][] ->
MultipleDispatchEventHandler'1[[SpecialCustomerMovedEvent]].
Now the question is of course: how can I fix the configuration (or the design) to support this?
I'm going to make this a separate answer instead of modifying my other one. This one solves the example scenario without using a composite.
Working Code
I added a static int handleCount to each of the event handlers for testing purposes, like this:
public class CustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public static int handleCount = 0;
public void Handle(CustomerMovedEvent e) { handleCount++; }
}
Here's a passing test that demonstrates that the events are going where they should:
var builder = new ContainerBuilder();
builder.RegisterSource(new Autofac.Features
.Variance.ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IEventHandler<>).Assembly)
.AsClosedTypesOf(typeof(IEventHandler<>));
builder.RegisterGeneric(typeof(EventRaiser<>))
.As(typeof(IEventRaiser<>));
var container = builder.Build();
Assert.AreEqual(0, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<CustomerMovedEvent>>()
.Raise(new CustomerMovedEvent());
Assert.AreEqual(1, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<CustomerMovedAbroadEvent>>()
.Raise(new CustomerMovedAbroadEvent());
Assert.AreEqual(2, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(2, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<SpecialCustomerMovedEvent>>()
.Raise(new SpecialCustomerMovedEvent());
Assert.AreEqual(3, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(3, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, CustomerMovedAbroadEventHandler.handleCount);
You can see I'm using an IEventRaiser<TEvent> instead of a composite IEventHandler<TEvent>. Here's how it looks:
public interface IEventRaiser<TEvent>
{
void Raise(TEvent e);
}
public class EventRaiser<TEvent> : IEventRaiser<TEvent>
{
List<IEventHandler<TEvent>> handlers;
public EventRaiser(IEnumerable<IEventHandler<TEvent>> handlers)
{
this.handlers = handlers.ToList();
}
public void Raise(TEvent e)
{
handlers.ForEach(h => h.Handle(e));
}
}
Design Thoughts
Avoiding the composite IEventHandler sure makes our work at the composition root easier. We don't have to worry about recursive composition or making sure the composite is the default implementation. But we added a new interface IEventRaiser which might look redundant. Is it? I think not.
Raising an event and handling an event are two different things. IEventHandler is an interface that has to do with handling events. IEventRaiser is an interface that has to do with raising events.
Imagine that I'm a piece of code that wants to raise an event. If I ask the IoC for a single IEventHandler I am introducing coupling that I don't need. I shouldn't need to know about that IEventHandler interface. I shouldn't be asking anyone to Handle my event. All I want to do is Raise it. Handling may or may not happen on the other side; it is irrelevant to me. I'm selfish - I want an interface created solely for me and my need to raise events.
As an event raiser, I intend to raise an event. As an event handler, I intend to handle an event. We have two different intents, so we should have two different interfaces. Just because we could use the same interface and a composite doesn't mean we should.
The Interface Segregation Principle seems to be more about splitting fat interfaces into thinner ones (see also Role Interface). In our case, we don't have a fat interface, but I think we're doing something similar - "Interface Segregation by Intent".
One more thing
In writing this answer I almost articulated a design idiom that I think many of us are familiar with, but I don't think we have standard terminology for it.
"Type C Interface" - frequently Consumed, rarely Implemented. A "service" interface. For example, IEventRaiser or ICustomerRepository. These interfaces probably have only one implementation (maybe decorated a bit) but they are consumed all over the place by code that wants to Raise Events or Save Customers.
"Type I Interface" - frequently Implemented, rarely Consumed. A "plugin" interface. For example, IEventHandler<TEvent>. Consumed in only one place (the EventRaiser) but implemented by many classes.
The same interface should not be both a Type C and a Type I. This is another reason to separate the IEventRaiser (Type C) from the IEventHandler (Type I).
I'm thinking that the composite pattern is only applicable to Type C interfaces.
Please edit or comment if there is standard terminology for what I've called "Type C" and "Type I" interfaces.
+1 for IEventRaiser<T> by #default.kramer. Just for the record, since the linked answer doesn't provide any code, and the configuration for this scenario is a bit less than intuitive because of the generic types involved:
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(...)
.As(t => t.GetInterfaces()
.Where(i => i.IsClosedTypeOf(typeof(IEventHandler<>)))
.Select(i => new KeyedService("handler", i)));
builder.RegisterGeneric(typeof(MultipleDispatchEventHandler<>))
.As(typeof(IEventHandler<>))
.WithParameter(
(pi, c) => pi.Name == "handlers",
(pi, c) => c.ResolveService(
new KeyedService("handler", pi.ParameterType)));