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