简体   繁体   中英

Ninject and Dependency Injection WebApi Attributes

I use Ninject:

public static class NinjectWebCommon
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <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>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        var resolver = new NinjectSignalRDependencyResolver(kernel);
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(kernel);

            RegisterServices(kernel);

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

            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<TMS.Entities.AssetContext>().ToSelf().InRequestScope();
        kernel.Bind<TMS.Data.IDbContext>().To<TMS.Entities.AssetContext>().InRequestScope();
        kernel.Bind(typeof(TMS.Data.IRepository<>)).To(typeof(TMS.Data.EfRepository<>));

        kernel.Bind<IExportManager>().To<ExportManager>().InRequestScope();
        kernel.Bind<IDriverService>().To<Services.Drivers.DriverService>().InRequestScope();
        .....
    }
}

It works fine for Mvc and Api controller. But right now I'm writing ActionFilter:

public class AccessLoadApiAttribute : ActionFilterAttribute
{
    public AccessLoadApiAttribute()
    {

    }

    private readonly ILoadServiceEntity _loadServiceEntity;
    public AccessLoadApiAttribute(ILoadServiceEntity loadServiceEntity)
    {
        _loadServiceEntity = loadServiceEntity ?? throw new ArgumentNullException(nameof(loadServiceEntity));
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var loadId = Convert.ToInt32(actionContext.RequestContext.RouteData.Values["Id"]);
        _loadServiceEntity.GetLoadById(loadId);

        base.OnActionExecuting(actionContext);
    }
}

and _loadServiceEntity is null. What is wrong in configuring?

In Asp.Net Web API 2.x, Attributes do not allow dependency injection via constructor if you want to use them on individual actions.

You would have to use the service locator anti pattern via the IDependencyResolver which can be accessed via the HttpConfiguration

For example

public class AccessLoadApiAttribute : ActionFilterAttribute {

    public override void OnActionExecuting(HttpActionContext actionContext) {
        //get the resolver via the request context
        var resolver = actionContext.RequestContext.Configuration.DependencyResolver;
        //use resolver to get dependency
        ILoadServiceEntity _loadServiceEntity = (ILoadServiceEntity)resolver.GetService(typeof(ILoadServiceEntity));
        var loadId = Convert.ToInt32(actionContext.RequestContext.RouteData.Values["Id"]);
        _loadServiceEntity.GetLoadById(loadId);
        base.OnActionExecuting(actionContext);
    }
}

The attribute can now be used as needed

[AccessLoadApi]
[HttpGet]
public IHttpActionResult SomeGetAction() {
    return Ok();    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM