Bradley Braithwaite
1 import {
2 Learning,
3 JavaScript,
4 AngularJS
5 } from 'Brad on Code.com'
6 |
Check out my online course: AngularJS Unit Testing in-depth with ngMock.

Domain Events with Ninject and ASP.Net Web API

on
on Design Patterns, c#, ASP.Net WebForms
This post looks at hooking up domain events to implementations using an IoC container and the ASP.Net Web API. This post is part of a blog series ASP.Net 10 Years On. Even though this is part of a series each post tries to be standalone. In the previous post we created the .Net Web API.

In an earlier post the topic of Domain Events in a domain model was discussed. This post revisits this and looks at how the concrete implementations can be injected using Ninject.

To recap, we had the DomainEvents class as follows:
public static class DomainEvents
{
/// <summary>
/// The _actions.
/// </summary>
/// <remarks>Marked as ThreadStatic that each thread has its own callbacks</remarks>
[ThreadStatic]
private static List<Delegate> _actions;

/// <summary>
/// The container
/// </summary>
public static IEventContainer Container;

/// <summary>
/// Registers the specified callback for the given domain event.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="callback">The callback.</param>
public static void Register<T>(Action<T> callback) where T : IDomainEvent
{
if (_actions == null)
_actions = new List<Delegate>();

_actions.Add(callback);
}
/// <summary>
/// Raises the specified domain event and calls the event handlers.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainEvent">The domain event.</param>
public static void Raise<T>(T domainEvent) where T : IDomainEvent
{
if (Container != null)
foreach (var handler in Container.Handlers(domainEvent))
handler.Handle(domainEvent);

// registered actions, typically used for unit tests.
if (_actions != null)
foreach (var action in _actions)
if (action is Action<T>)
((Action<T>)action)(domainEvent);
}
}
Since the initial post on domain events, the following has been added:
public static IEventContainer Container;
Plus the following code in the Raise method that checks the Container property for any handlers to be called:
   
if (Container != null)
foreach (var handler in Container.Handlers(domainEvent))
handler.Handle(domainEvent);
These two additions provide the link between this class and the IoC container of choice, which in this case is Ninject.
The IEventContainer is as follows:
public interface IEventContainer
{
IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent;
}
To get up and running using Ninject for the Web API we firstly need to go ahead and install Ninject via the Nuget Package Manager (see the post titled creating your first API under the heading "dependency injection" for more details on how to set this up). Next add the following class. This class allows us to interface the domain event handlers with Ninject:
public class NinjectEventContainer : IEventContainer
{
private readonly IKernel _kernerl;

public NinjectEventContainer(IKernel kernal)
{
_kernerl = kernal;
}

public IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent) where T : IDomainEvent
{
return _kernerl.GetAll<IDomainEventHandler<T>>();
}
}
Next we add the following line to the NinjectWebCommon.CreateKernel() method and the concrete implementations can be hooked up using dependency injection:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

// this is our concrete implementation of handler for winner selected event
kernel.Bind<IDomainEventHandler<WinnerSelectedEvent>>().To<WinnerSelectedHandler>();

GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

// ** WIRE UP DOMAIN EVENTS CONTAINER **
DomainEvents.Container = new NinjectEventContainer(kernel);

return kernel;
}
Here's the structure of the WinnerSelectedHandler class:
public class WinnerSelectedHandler : IDomainEventHandler<WinnerSelectedEvent>
{
public void Handle(WinnerSelectedEvent domainEvent)
{
// send a message here.
}
}
The source code for this project can be found at: github.com/bbraithwaite/smsquiz.
Key code elements discussed in this post:
SHARE
Don't miss out on the free technical content:

Subscribe to Updates

CONNECT WITH BRADLEY

Bradley Braithwaite Software Blog Bradley Braithwaite is a software engineer who works for search engine start-ups. He is a published author at pluralsight.com. He writes about software development practices, JavaScript, AngularJS and Node.js via his website . Find out more about Brad. Find him via:
You might also like:
mean stack tutorial AngularJS Testing - Unit Testing Tutorials