Autofac Несколько жизненных областей с одним контейнером - PullRequest
2 голосов
/ 15 апреля 2019

Я пытаюсь найти обходной путь использования нескольких сроков жизни с одним контейнером.

Проблема связана с реализацией InstancePerRequest().

Существует приложение, основанное наWebAPI с пользовательским WebHandler, поэтому Autofac не может определить, инициализирован или удален LifetimeScope.Поэтому я не могу использовать базовый InstancePerRequest().Я решил реализовать полу-заказ InstancePerRequest() в соответствии с Документация Autofac

Регистрация Autofac выглядит следующим образом:

...
private static IContainer Container;

private static void RegisterServices()
{
    var builder = new ContainerBuilder();
    builder.Register((c, p) => new CustomClass(p.Named<List<int>>("codes"), p.Named<User>("user")))
            .InstancePerRequest();

    Container = builder.Build();
}

public static ILifetimeScope BeginLifetimeScope()
{  
    return Container.BeginLifetimeScope(new[] { MatchingScopeLifetimeTags.RequestLifetimeScopeTag });
}
...

MatchingScopeLifetimeTags.RequestLifetimeScopeTag требуется в Autofac Customсемантика для каждого запроса согласно этой статье (точка 2)

Итак, я вручную создаю LifetimeScope:

... // AutofacHelper.BeginLifetimeScope() is implemented above
using (var lifetimeScope = AutofacHelper.BeginLifetimeScope())
{
    result = InvokeRequest(request.Api, context);
} 
...

Проблема в том, что их столько LifetimeScope как запросы.И область, в которой я нуждаюсь, начинается далеко от кода, где мне нужно получить к нему доступ.Мне нужен доступ к текущей области из любого места.

Я думаю, мне нужно пометить каждые LifetimeScope HttpContext.Current, и это будет достаточно уникально, чтобы определить, какую область мне нужно использовать.

Но как мне это сделать?Реализация BeginLifetimeScope() с параметром new[] { MatchingScopeLifetimeTags.RequestLifetimeScopeTag, HttpContext.Current } приводит к исключению, так как он не может найти запрошенную область.

Есть ли способ определить, какая область используется в текущем запросе?Например, используя мой собственный уникальный тег?ILifetimeScope имеет реализацию только для родительских областей.Есть ли причина для того, чтобы не использовать дочерние области, чтобы я мог использовать их в соответствии с HttpContext.Current?

Любые идеи?

Спасибо!

1 Ответ

1 голос
/ 15 апреля 2019

Я думаю, что то, что у вас есть, на самом деле совершенно правильно.

Проблема в том, что LifetimeScope имеет столько же запросов, сколько и

Это не проблема, вот как это работает. Даже в ASP.NET Core сегодня, и даже не только в режиме Autofac - экземпляр на запрос означает один срок действия на запрос.

У вас есть несколько вариантов для отслеживания продолжительности жизни.

Во-первых, вы можете внедрить ILifetimeScope в любой конструктор, и то, что вводится, - это область действия, которой принадлежит объект. Поэтому, если у вас есть что-то зарегистрированное InstancePerRequest, вы можете просто добавить параметр конструктора ILifetimeScope ... и он получит область запроса.

Во-вторых, вы всегда можете сохранить время жизни в HttpContext.Current при его создании.

using (var lifetimeScope = AutofacHelper.BeginLifetimeScope())
{
    HttpContext.Current.Items["RequestLifetimeScope"] = lifetimeScope;
    result = InvokeRequest(request.Api, context);
} 

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

var scope = (ILifetimeScope)HttpContext.Current.Items["RequestLifetimeScope"];
var x = scope.Resolve<IService>();

Если вы хотите больше указателей на то, где вы можете хранить область, как вы можете получить к ней доступ ... или даже если вы хотите использовать некоторые из встроенных помощников, я бы проверил источник для интеграция с Autofac WebAPI . Вам также может быть интересно посмотреть, как сам Web API перемещает область запроса - он хранит область вместе с сообщением входящего запроса , так что вы можете вызвать message.GetDependencyScope() и получить текущую область действия времени жизни. Вы могли бы сделать что-то подобное.

Если вы используете конвейер OWIN, то есть Интеграция OWIN для WebAPI, также , которая может дать вам некоторые идеи о том, как все подключено.

...