I'm trying to introduce domain events into a project. The concept is described in Udi Dahan's post - http://www.udidahan.com/2009/06/14/domain-events-salvation/
Here's the domain event code
public interface IDomainEvent { }
public interface IHandleDomainEvents<T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEventDispatcher
{
void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent;
}
public static class DomainEvents
{
public static IEventDispatcher Dispatcher { get; set; }
public static void Raise<TEvent>(TEvent eventToRaise) where TEvent : IDomainEvent
{
Dispatcher.Dispatch(eventToRaise);
}
}
The most important part is the IEventDispatcher implementation that decouples the domain event from whatever needs to happen when the event is raised. The trick is to wire up this coupling through a container. Here's my attempt
Code for Registering all Domain event handlers....
var asm = Assembly.GetExecutingAssembly();
var handlerType = typeof(IHandleDomainEvents<>);
builder.RegisterAssemblyTypes(asm)
.Where(t => handlerType.IsAssignableFrom(t)
&& t.IsClass
&& !t.IsAbstract)
.AsClosedTypesOf(handlerType)
.InstancePerLifetimeScope();
And resolving all the event handlers in the dispatcher. The problem is no handlers are resolved.
public class EventDispatcher : IEventDispatcher
{
private readonly IContainer _container;
public EventDispatcher(IContainer container)
{
_container = container;
}
public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent
{
var handlers = _container.Resolve<IEnumerable<IHandleDomainEvents<TEvent>>>().ToList();
handlers.ForEach(handler => handler.Handle(eventToDispatch));
}
}
So I'm not registering the event handlers correctly or not resolving them. How do I check that the registration is working?
Example code of a handler
public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated>
{
private readonly IConfig _config;
public SendWebQuestionToCSO(IConfig config)
{
_config = config;
}
public void Handle(JobNoteCreated args)
{
var jobNote = args.JobNote;
using(var message = new MailMessage())
{
var client = new SmtpClient {Host = _config.SmtpHostIp};
message.From = new MailAddress(_config.WhenSendingEmailFromWebProcessUseThisAddress);
...... etc
}
}
}
UPDATE After some trial and error the EventDispatcher is working ok! If I manually register a handler and then fire the domain event it works. The assembly scanning/registraion is my problem. The manual registration code...
builder.RegisterType<SendWebQuestionToCSO >().As<IHandleDomainEvents<JobNoteCreated>>();
So how do I scan all assemblies for all IHandleDomainEvents<>
given they look like this
public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated>
As Peter pointed out, the registration problem was with your Where()
clause.
When scanning assemblies Autofac filters components automatically based on the services you specify, so it would be equally correct to just use:
builder.RegisterAssemblyTypes(asm)
.AsClosedTypesOf(handlerType)
.InstancePerLifetimeScope();
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