I want to implement DI inside ActionFilterAttribute by Ninject. I've found this manual (actually I've read tens of them today) but it's for Unity. My attempt to implement it on Ninject is here:
public class MyFilter : ActionFilterAttribute
{
[Inject]
public IDepend Depend { get; set; }
// another code
}
bindings:
public class NinjectResolver : IDependencyResolver
{
// another code
private IKernel AddRequestBindings(IKernel kernel)
{
// another code
kernel.Bind<IDepend>().To<Depend>();
return kernel;
}
}
custom FilterProvider:
public class WebApiNinjectActionFilterProvider : ActionDescriptorFilterProvider, IFilterProvider
{
private readonly IKernel _kernel;
private readonly IEnumerable<IFilterProvider> _filterProviders;
public WebApiNinjectActionFilterProvider(IKernel kernel, IEnumerable<IFilterProvider> filterProviders)
{
_kernel = kernel;
_filterProviders = filterProviders;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var filters = _filterProviders.SelectMany(fp => fp.GetFilters(configuration, actionDescriptor)).ToList();
foreach (var filter in filters)
{
// GET ActivationException HERE!!!!!
_kernel.Inject(filter.Instance);
}
return filters;
}
public static void RegisterFilterProviders(IKernel ninjectKernel)
{
var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();
GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider),
new WebApiNinjectActionFilterProvider(ninjectKernel, providers));
var defaultprovider = providers.First(i => i is ActionDescriptorFilterProvider);
GlobalConfiguration.Configuration.Services.Remove(typeof(IFilterProvider), defaultprovider);
}
}
is called from WebApiConfig:
public static void Register(HttpConfiguration config)
{
var ninjectKernel = new StandardKernel();
config.DependencyResolver = new NinjectResolver(ninjectKernel);
WebApiNinjectActionFilterProvider.RegisterFilterProviders(ninjectKernel);
}
and finally action:
[MyFilter]
public async Task<string> Test()
{
return "Hello world";
}
The problem is I get an ActivationException in this line:
_kernel.Inject(filter.Instance);
ActivationException's Activation path:
2) Injection of dependency IDepend into property Depend of type MyFilter
1) Request for MyFilter
If to inject same property to controller - it injects fine. Any ideas how to improve my code?
I was doing IActionFilter DI in wrong way. The right way I've found in this blogpost of Mark Seemann.
DI via Ninject was implemented this way:
var myFilter = new MyFilter(ninjectKernel.Get<IDepend>());
config.Filters.Add(myFilter);