7

我是使用 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] 属性)从我的通用处理程序中获取一些服务时,我总是得到空值。这就是我的处理程序的样子:

    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) 确保您没有意外创建多个内核。"

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

4

3 回答 3

8

您可以使用依赖解析器:

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 运行时实例化的。

于 2012-05-04T10:07:23.247 回答
6

s的合成根IHttpHandlerIHttpHandlerFactory。您可以创建一个自定义 IHttpHandlerFactory,使用 Ninject 创建您的IHttpHandler. 这样你就可以使用构造函数注入。

于 2012-05-04T10:47:46.977 回答
2

我看到您的代码段中有一个“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
    }
}

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

网络配置:

  <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>();
}
于 2018-10-31T17:30:16.270 回答