Ninject和依赖注入WebApi属性

时间:2018-09-12 12:23:24

标签: c# asp.net-web-api dependency-injection ninject action-filter

我使用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();
        .....
    }
}

它适用于Mvc和Api控制器。但是现在我正在编写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);
    }
}

_loadServiceEntity为空。配置有什么问题?

1 个答案:

答案 0 :(得分:2)

在Asp.Net Web API 2.x中,如果要在单个操作上使用属性,则不允许通过构造函数进行依赖项注入。

您将必须通过IDependencyResolver使用服务定位器反模式,可以通过HttpConfiguration

对其进行访问。

例如

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);
    }
}

现在可以根据需要使用该属性

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