Как разрешить Autofac InstancePerHttpRequest

Я зарегистрировал такой компонент в моем файле Global.asax.cs:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());

builder.RegisterType<WebWorkContext>().As<IWorkContext>().InstancePerHttpRequest();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

// This is where my error happens, not sure why?
var workContext = container.Resolve<IWorkContext>();

WebWorkContext класс:

public class WebWorkContext : IWorkContext
{
     // Left out other code
}

IWorkContext интерфейс:

public interface IWorkContext
{
     // Left out other code
}

Ошибка, которую я получаю:

Никакая область с тегом, сопоставляющим "httpRequest", видна из области, в которой запрашивался экземпляр. Обычно это указывает на то, что компонент, зарегистрированный как HTTP-запрос, запрашивается компонентом SingleInstance() (или аналогичным сценарием). В рамках веб-интеграции всегда запрашиваются зависимости от DependencyResolver.Current или ILifetimeScopeProvider.RequestLifetime, никогда из самого контейнера.

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

Еще несколько вопросов. Является ли разумным/лучшим методом регистрироваться каждый раз? Будут ли сценарии, которые мне потребуются, чтобы добавить другие компоненты на другом этапе?

Ответы

Ответ 1

Ожидается, что регистрации, отмеченные InstancePerHttpRequest, будут разрешены из определенной вложенной области времени жизни, которая создается и удаляется во время каждого HTTP-запроса.

Если вы добавите IWorkContext в качестве параметра конструктора в один из ваших контроллеров, вы обнаружите, что экземпляр вводится. В вашем коде вы пытаетесь разрешить свою службу из области жизненного цикла root, а не вложенной области действия "на запрос".

Если вы хотите протестировать решение службы без запуска вашего приложения, вам потребуется создать область времени жизни с тем же тегом, что и те, что были созданы во время HTTP-запроса. В интеграции MVC 3 область действия времени помечена как "httpRequest".

using (var httpRequestScope = container.BeginLifetimeScope("httpRequest"))
{
    Assert.That(httpRequestScope.Resolve<IWorkContext>(), Is.Not.Null);
}

Я думаю, что я обновлю интеграцию MVC, чтобы публично публиковать имя тега "httpRequest" через API, чтобы строковые значения не нуждались в жестком кодировании. Также можно передать свою собственную реализацию ILifetimeScopeProvider в AutofacDependencyResolver, чтобы вы могли управлять созданием областей жизненного цикла вне среды выполнения ASP.NET. Это полезно при модульных тестах, когда HTTP-запрос недоступен.

Ответ 2

Я делаю это в WebForms:

this.RoutingService = ((Global)HttpContext.Current.ApplicationInstance).ContainerProvider.RequestLifetime.Resolve<RoutingService>();