I'm guessing there is no way to do something like the following with Autofac, to ctor inject an enumerable collection of open generic types? The various Handle types have dependencies, otherwise I would just dynamically build those up.
class EventOne : IEvent {...}
class EventTwo : IEvent {...}
class EventThree : IEvent {...}
interface IHandleEvent<T> where T : IEvent {...}
class HandleEventOne : IHandleEvent<EventOne> {...}
class HandleEventTwo : IHandleEvent<EventTwo> {...}
class HandleEventThree : IHandleEvent<EventThree> {...}
builder.RegisterAssemblyTypes(myAssembies).AsClosedTypesOf(typeof(IHandleEvent<>));
builder.RegisterType<AService>().As<IAService>();
class AService : IAService
{
public AService(IEnumerable<IHandleEvent<IEvent>> handles)
{...}
}
As explained in the comments, what you want is impossible to achieve in C# and with good reason. If you were able to cast an IHandleEvent<EventOne>
to an IHandleEvent<IEvent>
it would allow an EventTwo
to be passed in as well, which would fail at runtime.
So what you need is an mediator abstraction that allow getting all the compatible event handlers and call them. Such mediator is often called IEventPublisher
and might look like this:
public interface IEventPublisher {
void Publish(IEvent e);
}
You can now create a container specific implementation. For instance, for Autofac this would look as follows:
public class AutofacEventPublisher : IEventPublisher {
private readonly IComponentContext container;
public AutofacBusinessRuleValidator(IComponentContext container) {
this.container = container;
}
public void Publish(IEvent e) {
foreach (dynamic handler in this.GetHandlers(e.GetType())) {
handler.Handle((dynamic)e);
}
}
private IEnumerable GetHandlers(Type eventType) =>
(IEnumerable)this.container.Resolve(
typeof(IEnumerable<>).MakeGenericType(
typeof(IHandleEvent<>).MakeGenericType(eventType)));
}
Consumers can now depend on this new abstraction:
class AService : IAService
{
public AService(IEventPublisher publisher) {...}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With