Время жизни Autofac и поставщик по умолчанию в соответствующей области времени жизни
У меня есть 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", не видна из области
в котором был запрошен экземпляр. Это обычно указывает на то, что a
компонент, зарегистрированный в качестве отдельного HTTP-запроса будет reqested по
Компонент SingleInstance () (или аналогичный сценарий.) Под паутиной
интеграция всегда запрашивает зависимости от
DependencyResolver.Текущий или ILifetimeScopeProvider.RequestLifetime,
никогда из самого контейнера.
Я знаю, что Autofac всегда использует последнего зарегистрированного поставщика в качестве поставщика по умолчанию для конкретного компонента. Я сделал предположение, что он будет использовать последний зарегистрированныйподходящий провайдер.
Я что-то упустил, или есть лучший подход к выбору поставщика основываясь на теге текущей области жизненного цикла?
2 ответов:
Зарегистрируйте веб-Фу как обычный, но не регистрируйте другой Фу. При создании области жизни для асинхронной задачи используйте перегрузку BeginLifetimeScope (), которая выполняет действие над ContainerBuilder. Зарегистрируйте фоновый Foo в этом действии (b => b.Register ()), и это должно переопределить веб-один. (Маленькая клавиатура здесь Извините :))
Это также можно решить с помощью помеченной области времени жизни. Зарегистрировать свой первый Фу как экземпляр помеченные сфера:
builder.RegisterType<Foo>().As<IFoo>.InstancePerMatchingLifetimeScope("YourScopeTag");И создайте область с тем же тегом, который вы зарегистрировали в dependencie:
using (var Scope = Runtime.Container.BeginLifetimeScope("YourScopeTag")) { var Input = Scope.Resolve<T>(); action(Input); }Не проверял его, но он должен работать
Http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-matching-lifetime-scope
Comments