Внедрение свойства HttpHandler с использованием Ninject, возвращающего null

У меня есть следующий 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;
        }
    }
}

Это мой модуль Ninject в Global.asax.

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

Каждый раз, когда обработчик запускает FileReader, значение NULL. Я что-то упускаю? Это правильный способ внедрения свойств с помощью Ninject?

Спасибо


person Thomas    schedule 02.09.2010    source источник


Ответы (2)


Это правильный способ внедрения свойств с помощью Ninject, но он не сработает. Вероятно, вы используете что-то вроде класса NinjectMvcApplication в качестве базового класса для вашего приложения, которое обрабатывает внедрение зависимостей для контроллеров и всего, что могут использовать контроллеры (сервисы, репозитории). Но экземпляры HttpHandler не создаются 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;
        }
    }
}
person Necros    schedule 02.09.2010
comment
Спасибо! Прочитал статью, интересно. Просто чтобы попробовать, я изменил свое приложение соответствующим образом, но мне все еще удается получить NULL в свойстве FileReader, когда срабатывает ProcessRequest. - person Thomas; 03.09.2010
comment
Да, такой подход работает. Все еще любопытно, почему httphandlers не могут выполнять инъекции свойств так же, как контроллер. Вероятно, что-то делать с конвейером запросов. Если кто-нибудь знает, пожалуйста, дайте мне знать. Некрос, еще раз спасибо! - person Thomas; 03.09.2010
comment
Как я объяснил в своем ответе, фабрика контроллеров заботится о внедрении в контроллеры. Если вы хотите автоматически внедряться в HttpHandlers, вам нужно взять под контроль то, что создает HttpHandlers — msdn.microsoft.com/en-us/library/ms227439%28v=VS.100%29.aspx - person Necros; 03.09.2010

Если вы используете Ninject.Web.Common, у вас должен быть файл NinjectWebCommon.cs в папке app_start. Этот класс создает экземпляр класса Bootstrapper, который содержит одноэлементный экземпляр ядра Ninject. Это ядро ​​​​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>();
}
person Thomas Johnson    schedule 31.10.2018
comment
Я читал, что в более поздних версиях ninject web common вы можете просто наследовать от Ninject.Web.HttpHandlerBase, и это должно работать. Попробуйте это в первую очередь, если вы читаете это. - person Thomas Johnson; 02.11.2018
comment
Это сработало для меня! Нужна только одна строка в web.config - бит в system.webServer - person B.Mo; 08.02.2021