Background -
I am working on a service that internally raises domain events (those are raised through IDomainEventsAggregator.AddEvent
. When an operation finishes (i.e. Transaction or an HTTP Request), these events are published to respective handlers through MediatR
. Those MediatR
are Notification
handlers to handle the domain events.
Here is sample code
I have the following code (simplified) which represents domain events -
public interface IDomainEvent{}
public class ADomainEvent:IDomainEvent {}
public class BDomainEvent:IDomainEvent {}
And the following class for a collection of domain events (an event bag):
public class DomainEventsBag<TDomainEvent> where TDomainEvent: IDomainEvent
{
public DomainEventsBag(IEnumerable<TDomainEvent> domainEvents)
{
DomainEvents = domainEvents;
}
public IEnumerable<TDomainEvent> DomainEvents { get; }
}
And Respective handlers are ...
public class ADomainEventNotificationHandler1:INotification<DomainEventsBag<ADomainEvent>>{ ... code to handle domain event of type ADomainEvent ...}
public class ADomainEventNotificationHandler2:INotification<DomainEventsBag<ADomainEvent>>{ ... code to handle domain event of type ADomainEvent ...}
public class BDomainEventNotificationHandler:INotification<DomainEventsBag<BDomainEvent>>{ ... code to handle domain event of type BDomainEvent ...}
A service that aggregates all domain events
public interface IDomainEventsAggregator
{
void AddEvent<TDomainEvent>(TDomainEvent event) where TDomainEvent:IDomainEvent;
void Commit();
}
public class DomainEventsAggregator:IDomainEventsAggregator
{
private IMediator mediator;
private Dictionary<Type, List<IDomainEvent>> domainEvents;
public DomainEventAggregator(IMediator mediator)
{
this.mediator = mediator;
domainEvents = new Dictionary<Type, List<IDomainEvent>>();
}
public void AddEvent<TDomainEvent>(TDomainEvent event) where TDomainEvent:IDomainEvent
{
if (!domainEvents.ContainsKey(typeof(TDomainEvent)))
domainEvents.Add(typeof(TDomainEvent), new List<IDomainEvent>());
domainEvents[typeof(TDomainEvent)].Add(domainEvent);
}
public void Commit()
{
foreach (var @event in domainEvents)
{
// **************************
// This is where I need help!
// To generate object of type DomainEventsBag<@event.Key> since @event.Key is type of event so that following line with work
domainEventsBag = ??? // the code which I am not able to write or solution I am looking for
// **************************
mediator.Publish(domainEventsBag);
// Actual problem - mediator handler will execute only if domainEventsBag has concrete type (i.e. ADomainEvent or BDomainEvent) instead of IDomainEvent = DomainEventsBag<ADomainEvent> and DomainEventsBag<BDomainEvent>.
}
}
}
I tried Activator.CreateInstance but it does not since it throws an error for missing parameter on CTOR of type. Here is a sample of what I tried to create a dynamic object -
var type = typeof(DomainEventsBag<>).MakeGenericType(@event.Key);
var eventBag = Activator.CreateInstance(type, @event.Value);
Two problems with the above code -
- It throws an error that the CTOR with argument type @event.Value (For example ADomainEvent) is missing
- The return type of Activator.CreateInstance is an object instead of DomainEventsBag