Как разрешить 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>();