У меня есть веб-приложение ASP.NET MVC, использующее Autofac для инъекции зависимостей. Время от времени это веб-приложение запускает поток для выполнения некоторой работы отдельно от потока запроса. Когда этот фоновый поток запускается, он устанавливает новую область времени Autofac от корневого контейнера и выполняет некоторые действия.
public IAsyncResult Run<T>(Action<T> action)
{
var NewTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
using (var Scope = Runtime.Container.BeginLifetimeScope())
{
var Input = Scope.Resolve<T>();
action(Input);
}
});
return NewTask;
}
Одна из моих зависимостей, зарегистрированных в Autofac, имеет две различные реализации: одна подходит для времени жизни http-запросов, а другая - для всех остальных времен жизни. Я попытался зарегистрировать их следующим образом:
builder
.Register(c => new Foo())
.As<IFoo>()
.InstancePerLifetimeScope();
builder
.Register(c => new FooForHttp(HttpContext.Current))
.As<IFoo>()
.InstancePerMatchingLifetimeScope(WebLifetime.Request);
Autofac выбирает FooForHttp
для http-запросов (как и ожидалось). Однако, когда мой фоновый поток раскручивается, любая попытка разрешить IFoo
приводит к исключению:
Ни одна область видимости с тегом, соответствующим 'httpRequest', не видна из области видимости в которой был запрошен экземпляр. Это обычно указывает на то, что компонент, зарегистрированный как per-HTTP запрос, запрашивается компонентом SingleInstance() компонента (или аналогичный сценарий.) В рамках веб-интеграции интеграции всегда запрашиваются зависимости из DependencyResolver.Current или ILifetimeScopeProvider.RequestLifetime, никогда из самого контейнера.
Я знаю, что Autofac всегда использует последнего зарегистрированного провайдера в качестве провайдера по умолчанию для конкретного компонента. Здесь я сделал предположение, что он будет использовать последний зарегистрированный подходящий провайдер.
Я что-то упускаю, или есть лучший подход к выбору провайдера на основе тега текущей области действия?