2016-09-22 2 views
0

КонтроллерПравильно установить Scope при использовании WebAPI, SimpleInjector и MediatR

public class LocationsController : ApiController 
{ 
    private readonly IMediator _mediator; 

    public LocationsController(IMediator mediator) 
    { 
     _mediator = mediator; 
    } 

    public IEnumerable<Place> Get() 
    { 
     return _mediator.Send(new GetLatestMapData<Place>()); 
    } 
} 

По первому требованию Получить() действия, Handler конкретизируется путем SimpleInjector и выполняется правильно.

На втором запросе (F5 в браузере, например), он терпит неудачу с:

Обработчик не был найден для запроса типа ....

Контейнер или служба поиска не настроен должным образом или обработчиков, не зарегистрированных в вашем контейнере.

и внутреннее исключение:

Не удается получить доступ к объекту, расположенный.

Название объекта: «Объект ThreadLocal был удален».

Owin Startup

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     // SimpleInjector 
     var container = CompositionRoot.CreateContainer(); 

     var config = GlobalConfiguration.Configuration; 

     config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); 

     // Routing 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", 
      new { id = RouteParameter.Optional }); 

     config.EnsureInitialized(); 

     app.UseWebApi(config); 
    } 
} 

SimpleInjector IPackage для проекта WebAPI

public class Installer : IPackage 
{ 
    public void RegisterServices(Container c) 
    { 
     c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 

     c.RegisterWebApiControllers(GlobalConfiguration.Configuration); 
    } 
} 

Я думаю, что это правильно создан Handler, что происходит, а затем утилизировать после первого запроса. Теперь я не знаю почему, но при последующих запросах обработчик не воссоздается. Я знаю это, потому что, если я изменю WebApiRequestLifestyle к «не выбрасывайте, когда сфера заканчивается», он работает для каждого запроса:

c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(false 
/*disposeInstanceWhenScopeEnds*/); 

Вопросы

  1. Должен ли я сохранить параметр disposeInstanceWhenScopeEnds значение ЛОЖЬ?
  2. Если нет, то каково правильное решение?
  3. Я вижу, что это было solved before by creating a LifetimeScopeDecorator ... однако, эта функциональность уже предоставлена ​​библиотекой интеграции SimpleInjector WebApi? Что мне не хватает?

(И спасибо за чтение)

+0

Пожалуйста, добавьте соответствующие трассировки стека, – Steven

ответ

0

Это link обеспечивает хорошее руководство по разрешению зависимостей и использование IDependencyResolver/IDependencyScope интерфейсов.

Сразу же вы увидите, что они касаются жизненных промежутков, которые, как правило, немного сложны.

В этом разделе, в частности, интересно:

Dependenecy Scope и контроллер Lifetime

Контроллеры создаются по запросу. Для управления временем жизни объекта IDependencyResolver использует концепцию области.

Резолютор зависимостей, прикрепленный к объекту HttpConfiguration, имеет глобальный объем. Когда Web API создает контроллер, он вызывает BeginScope. Этот метод возвращает IDependencyScope, который представляет дочернюю область.

Web API затем вызывает GetService в области дочерних объектов для создания контроллера . По завершении запроса веб-API вызывает Dispose в области . Используйте метод Dispose для утилизации зависимостей контроллера.

Обычная загрузка службы произойдет один раз во время запуска приложения и, как вы знаете, разрешите любые зависимости в это время. Только тогда, когда рабочий процесс завершает работу (например, нет активности), тогда вызывается утилизация.

Обычно я считаю, что для разрешенных экземпляров вполне нормально оставаться в течение жизненного цикла, если не обязательно, чтобы они были уничтожены после использования. Но в приведенном примере объясняется, что мы должны правильно распоряжаться после завершения запроса. Поэтому я рекомендую вам правильно распоряжаться своими экземплярами, используя примеры, приведенные в качестве руководства.

Это помогло мне при работе с IoC и WebApi. Надеюсь, это поможет!

0

Вы должны организовать ваш Lifetime область действия

Код:

container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 

container.Options.LifestyleSelectionBehavior = new WebApiInjectionLifestyle(); 


internal class WebApiInjectionLifestyle : ILifestyleSelectionBehavior 
{ 
    public Lifestyle SelectLifestyle(Type serviceType, Type implementationType) 
    { 
     return Lifestyle.Scoped; 
    } 
} 

Более подробно

https://simpleinjector.readthedocs.io/en/latest/lifetimes.html