1

Я настроил мой контекст EF сконфигурировано как такКак разрешить Autofac каждого запроса услуги от пользовательского атрибута

 b.RegisterAssemblyTypes(webAssembly, coreAssembly) 
      .Where(t => t.IsAssignableTo<DbContext>()) 
      .InstancePerLifetimeScope(); 

Я хотел бы использовать его из пользовательского атрибута авторизации, который попадает в базу данных, используя свой контекст EF. Это означает, что нет инъекции конструктора. Я добиться этого с помощью CommonSeviceLocator

 var csl = new AutofacServiceLocator(container); 
     ServiceLocator.SetLocatorProvider(() => csl); 

...

 var user = await ServiceLocator.Current 
      .GetInstance<SiteContext>().FindAsync(id); 

Я нахожу, что это терпит неудачу с «множеством соединений не поддерживается» ошибок, если браузер выдает два одновременных запросов к маршрутам с помощью этого атрибута , Похоже, это может быть due to what is mentioned in this answer. Я предполагаю, что ServiceLocator разрешает из области корня, а не из области веб-запроса, и два запроса конфликтуют (либо запрос в изоляции работает нормально).

Это похоже на то, что когда я перехожу на InstancePerRequest(), я получаю это от любого вызова атрибута.

Autofac.Core.DependencyResolutionException No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is 
being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself. 

Так что похоже, может быть ServiceLocator просто не путь.

Как устранить область запроса SiteContext изнутри атрибута (используя шаблон сервис-локатор)?

+2

[Стандартные фильтры веб-API - это синглтоны] (http://autofac.readthedocs.org/ru/latest/integration/webapi.html#standard-web-api-filters-are-singletons). Вы можете проверить здесь. –

+0

@ErkanDemirel да, но его не так, как 'ServiceLocator' кэширует ответ, он получает новый по каждому вызову! Я предполагаю, что код фильтра запускается * до того, как * Autofac создает область запроса. –

+0

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

ответ

2

Ваш вопрос проистекает из того, что вы пытаетесь ввести поведение внутри Атрибута. Атрибуты предназначены для определения метаданных для элементов кода и сборок, а не для поведения.

Маркетинг Microsoft Action Filter Attributes побудил людей внедрять DI вниз по неправильному пути, поместив оба фильтра и атрибут в один класс. Как описано в посте passive attributes, решение распадаться filter attributes на 2 класса:

  1. Атрибут, который не содержит никакого поведения, чтобы отметить кодовые элементы с мета-данными.
  2. Глобально зарегистрированный фильтр, который сканирует атрибут и выполняет желаемое поведение, если оно присутствует.

См следующие дополнительные примеры:

Другой вариант заключается в использовании IFilterProvider разрешить фильтры, как в IFilterProvider and separation of concerns.

Как только вы узнаете, что Атрибуты не должны ничего делать сами, использование их с помощью DI довольно просто.

+0

Хорошо, я понимаю, что вы говорите ... но в первом примере, по крайней мере, не было бы той же проблемы? Фильтр разрешен в глобальной области действия, а не в области «AutofacWebRequest», и поэтому он будет синглом. Если у самого атрибута есть только один экземпляр, все жизненные циклы все те же, что и с шаблоном-локатором службы, не так ли? –

+1

Как отметил Эркэн в комментариях, есть две возможности этой проблемы: 1) использовать интерфейсы Autofac, а не интерфейсы WebAPI; 2) использовать локатор службы из области зависимости (которая передается через контекст). См. [Примеры] (http://autofac.readthedocs.org/en/latest/integration/webapi.html#standard-web-api-filters-are-singletons). Существует возможный третий вариант, более дружественный к DI - вводят [абстрактный завод] (http://blog.ploeh.dk/2014/05/19/di-friendly-framework/), чтобы создать экземпляр 'SiteContext' в пределах фильтра действий, а не с помощью локатора служб. – NightOwl888

+0

ах, я думаю, 2) это то, что я хочу. Разумеется, DI Friendly материал лучше, поэтому я мог бы попробовать это во-первых, но для немного изолированной инфраструктуры, такой как это ... meh ... –