【问题标题】:HttpHandler Property Injection using Ninject returning null使用 Ninject 的 HttpHandler 属性注入返回 null
【发布时间】:2010-09-02 17:12:15
【问题描述】:

我有以下 httphandler:

public class NewHandler : IHttpHandler
{
    [Inject]
    public IFile FileReader
    {
        get;
        set;
    }

    public NewHandler()
    {
    }

    public void ProcessRequest(System.Web.HttpContext context)
    {
        ....
        var something = SomeMethod(FileReader);
        ....
    }

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

这是我在 Global.asax 中的 Ninject 模块。

internal class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IFile>().To<FileWrapper>().InSingletonScope();
    }
}

每次处理程序触发 FileReader 时为 NULL。我错过了什么吗?这是使用 Ninject 进行属性注入的正确方法吗?

谢谢

【问题讨论】:

    标签: asp.net-mvc-2 ninject ninject-2


    【解决方案1】:

    这是使用 Ninject 进行属性注入的正确方法,但它不起作用。您可能正在使用类似 NinjectMvcApplication 类的东西作为应用程序的基类,它处理控制器的依赖注入以及控制器可能使用的所有内容(服务、存储库)。但是 HttpHandlers 不是由 ControllerFactory 实例化的,所以没有什么可以处理注入的东西。

    也许有更好的方法可以做到这一点,但我使用服务定位器来解决依赖关系。见http://code.dortikum.net/2010/08/05/asp-net-mvc-di-with-common-service-locator-and-ninject/

    更新:

    试试这样的:

    public class NewHandler : IHttpHandler
    {
        private readonly IFile _fileReader;
    
        public NewHandler()
        {
            _fileReader = ServiceLocator.Current.GetInstance<IFile>();
        }
    
        public void ProcessRequest(System.Web.HttpContext context)
        {
            ....
            var something = SomeMethod(_fileReader);
            ....
        }
    
        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
    

    【讨论】:

    • 谢谢!我读了这篇文章,很有趣。只是为了尝试一下,我相应地修改了我的应用程序,但是当 ProcessRequest 触发时,我仍然设法在 FileReader 属性中获取 NULL。
    • 是的,这种方法有效。仍然好奇为什么 httphandlers 不能像控制器一样进行属性注入。可能与请求管道有关。如果有人知道,请告诉我。死灵,再次感谢!
    • 正如我在回答中解释的那样,控制器工厂负责注入控制器。如果您想自动注入 HttpHandlers,则必须控制创建 HttpHandlers 的内容 - msdn.microsoft.com/en-us/library/ms227439%28v=VS.100%29.aspx
    【解决方案2】:

    如果您使用的是 Ninject.Web.Common,您的 app_start 文件夹中应该有一个 NinjectWebCommon.cs。该类实例化了一个包含 Ninject 内核的单例实例的 Bootstrapper 类。 Ninject 内核实际上在您的应用程序中随处可用,这意味着它也可以在 HTTP 工厂类中使用。

    您可以通过以下方式继续使用 Ninject,其方式或多或少与您使用控制器的方式相同:

    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)
    {
        // other bindings you already have
    
        // the binding for your handler factory
        Bind<IHttpHandler>().To<NewHandler>();
    }
    

    【讨论】:

    • 我读到了更高版本的 ninject web common,你可以从 Ninject.Web.HttpHandlerBase 继承,它应该可以工作。如果您正在阅读本文,请先尝试一下。
    • 这对我有用!虽然只需要 web.config 中的一行 - system.webServer 中的位
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多