Можно ли указать несколько областей действия Autofac при регистрации?
Я использую контейнер Autofac IoC с надстройкой MVC4, которая обеспечивает область действия InstancePerHttpRequest. Однако в рамках моего проекта у меня есть веб, веб-API и фоновые рабочие потоки. В следующем примере я предполагаю, что область действия InstancePerHttpRequest не имеет большого значения, если она не исходит из веб-запроса.
builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>()
.InstancePerHttpRequest()
Мне интересно, можно ли сделать что-то вроде следующего примера, и контейнер выберет наиболее подходящую область действия?
builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>()
.InstancePerHttpRequest()
.InstancePerApiRequest()
.InstancePerDependency();
В этом случае я намереваюсь произойти, если запрос происходит из веб-запроса, тогда он выберет область InstancePerHttpRequest, если он исходит из запроса webApi, он выберет область InstancePerApiRequest и, если он используется рабочими потоками приложения, он будет использовать область InstancePerDependency?
Есть идеи, если это или что-то подобное возможно?
Спасибо
1 ответ
Этот вопрос имеет довольно много общего с этими:
- Управление областями действия AutoFac для каждого сеанса и запроса в asp.net mvc 3
- Экземпляр на одну и ту же область действия с продолжительностью по умолчанию?
- Autofac - время жизни и модули
- Время жизни Autofac и поставщик по умолчанию в соответствующей области времени жизни
Вы хотите, чтобы проверить это для некоторых идей.
Короткий ответ: этот вид вещи не поддерживается прямо из коробки. Вам нужно будет сделать одну из нескольких вещей.
Опция: у вас может быть другой контейнер для фоновых потоков. Это не позволит вам делиться синглетами уровня приложения, но это может быть хорошо для вашего приложения.
Опция: Вы можете создать две области действия вне контейнера и выполнить различные регистрации в рамках вызова BeginLifetimeScope
, Это позволит вам совместно использовать синглтоны уровня приложения и иметь разные области действия для одних и тех же компонентов в разных контекстах. Однако немного сложнее управлять регистрациями, и вам понадобятся два разных сервисных локатора (например, DependencyResolver
) потому что каждый логический контекст должен был бы разрешаться из своей собственной области.
var builder = new ContainerBuilder();
builder.RegisterType<AppLevelSingleton>().SingleInstance();
var container = builder.Build();
// Create a nested lifetime scope for your background threads
// that registers things as InstancePerDependency, etc. Pass
// that scope to whatever handles dependency resolution on the thread.
var backgroundScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerDependency());
// Create a nested lifetime scope for the web app that registers
// things as InstancePerHttpRequest, etc. Pass that scope
// as the basis for the MVC dependency resolver.
var webScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerHttpRequest());
var resolver = new AutofacDependencyResolver(webScope);
DependencyResolver.SetResolver(resolver);
Если вы действительно хотите получить фантазию с этой опцией, вы можете реализовать IContainer
он может определить, в каком контексте он находится, и разрешить вещи из соответствующей вложенной области видимости. Вот как работает мультитенантная поддержка Autofac. Тем не менее, это гораздо более сложное решение, поэтому я не собираюсь писать все это здесь. Проверьте источник Autofac для поддержки мультитенанта для примеров.
Вариант: Вы можете использовать регистрацию типа "наименьший общий знаменатель", например InstancePerDependency
или же InstancePerLifetimeScope
и пропустить идею о различном времени жизни для разных частей приложения.
Обратите внимание, что сейчас, технически, внутренне, нет никакой разницы между тем, что InstancePerHttpRequest
а также InstancePerWebApiRequest
делать Они оба сводятся к одной и той же вещи и эффективно взаимозаменяемы. (Я не могу обещать, что так будет всегда, но я не знаю, почему это нужно изменить.)