如何使用Ninject注入一些通用的asp.net http处理程序?

时间:2012-05-04 10:04:58

标签: asp.net-mvc-3 ninject generic-handler

我是使用Ninject的新手,我无法弄清楚如何注入我的通用http处理程序。我有一个MVC3项目,我将我的服务注入到控制器中,没有任何问题。 这是我在Ninject App_start类中用于注册服务的内容:

        private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
        kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
        kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
        kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
        kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();

当我尝试通过使用属性注入(使用[inject]属性)从我的泛型处理程序获取某些服务时,我总是得到null。这就是我的处理程序的样子:

    public class SubscriberHandler : IHttpHandler
{
    [Inject]
    public INLUserRepository userRep { get; set;}

    public void ProcessRequest(HttpContext context)
    {
        var users = userRep.GetUsers(); //userRep is always null here
    }


    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

我也试过这样做:

    readonly INLUserRepository userRep;

    public SubscriberHandler()
    {

        using (IKernel kernel = new StandardKernel(new App_Start.NJRepositoryModule()))
        {
            userRep = kernel.Get<INLUserRepository>();
        }
    }

但我得到一个异常:“加载Ninject组件ICache时出错。在内核的组件容器中没有注册这样的组件。 建议:  1)如果您为KernelBase创建了自定义子类,请确保您已正确使用     实现了AddComponents()方法。  2)确保没有通过调用RemoveAll()从容器中删除组件。  3)确保您没有意外地创建了多个内核。“

这表明我不应该在我的应用程序中实例化多个内核,对吧? 我究竟做错了什么? 感谢

3 个答案:

答案 0 :(得分:5)

IHttpHandler s的组合根是IHttpHandlerFactory。您可以创建使用Ninject创建IHttpHandler实例的自定义IHttpHandlerFactory。这样你就可以使用构造函数注入。

答案 1 :(得分:4)

您可以使用依赖项解析器:

public class SubscriberHandler : IHttpHandler
{
    public INLUserRepository userRep { get; private set; }

    public SubscriberHandler()
    {
        userRep = DependencyResolver.Current.GetService<INLUserRepository>();
    }

    public void ProcessRequest(HttpContext context)
    {
        var users = userRep.GetUsers(); //userRep is always null here
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

我期待得到这个答案的负面反馈,因为服务定位器模式被许多人视为反模式。

但我不确定NInject是否允许您为HTTP处理程序使用构造函数注入,因为它们是由ASP.NET运行时实例化的。

答案 2 :(得分:0)

我看到您的代码段中有一个“ RegisterServices”方法,这表明您已经在使用Ninject.Web.Common。您可能不了解NinjectWebCommon.cs的地方是它使用Bootstrapper类,其中包含Ninject内核的单例实例。

如上面的Remo所述,IHttpHandlerFactory是IHttpHandler实例的组合根,因此,您将需要创建此接口的实现并将必要的配置元素添加到web.config。

MyHandlerFactory.cs:

public class MyHandlerFactory : IHttpHandlerFactory
{
    public bool IsReusable => false;

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
       // the bootstrapper class uses the singleton pattern to share the Ninject Kernel across your web app's ApplicationDomain
       var kernel = new Bootstrapper().Kernel;

       // assuming you have only one IHttpHandler binding in your NinjectWebCommon.cs
       return kernel.Get<IHttpHandler>();
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
       // nothing to release
    }
}

现在,为新的处理程序工厂添加必要的配置元素...

Web.config:

  <system.web>
    <httpHandlers>
      <add verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <handlers>
      <add name="MyHandlerFactory" verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" preCondition="integratedMode" />
    </handlers>
  </system.webServer>

最后,为您的IHttpHandler实现添加一个绑定...

NinjectWebCommon.cs:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
    kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
    kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
    kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
    kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();

    // the binding for your handler factory
    Bind<IHttpHandler>().To<SubscriberHandler>();
}