Overview
I ran into a problem today where I needed to inject dependencies into a handler. Typically, you don’t really have access to the kernel here and I saw this as a problem as my handler had its own dependencies which needed to be resolved.
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new {id = RouteParameter.Optional}
);
config.Services.Replace(typeof (IExceptionHandler), ***Err I need to be inject my concrete type here??**);
}
}
After much research, it doesn’t appear people use Ninject here…or they don’t document it…anyway, I decided to add a method to get the created kernel from the NinjectWebCommon class called GetKernel. Please note that this snippet also includes the declaration for a NinjectDependencyResolver.
public static class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
private static readonly IKernel _kernel = new StandardKernel();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof (OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof (NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
Bootstrapper.ShutDown();
}
/// <summary>
/// I added this method in order to get the kernel...
/// </summary>
public static IKernel GetKernel()
{
return _kernel;
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
_kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
_kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(_kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(_kernel);
return _kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Load(Assembly.GetExecutingAssembly());
}
}
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _kernel.GetAll(serviceType);
}
public void Dispose()
{
}
public IDependencyScope BeginScope()
{
return this;
}
}
Now I’ve exposed my kernel via this method I can then use it in the WebApiConfig class. This doesn’t seem ideal but there seems to be tons of different ways to configure Ninject dependant on the type of web project you’re creating.
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Getting the kernel via the exposed method
var kernel = NinjectWebCommon.GetKernel();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new {id = RouteParameter.Optional}
);
// Manually injecting the bound instance
config.Services.Replace(typeof (IExceptionHandler), kernel.Get<IExceptionHandler>());
}
}
If anyone has any better way to achieve the same results, please let me know in the comments!