Время жизни 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 всегда использует последнего зарегистрированного поставщика в качестве поставщика по умолчанию для конкретного компонента. Я сделал предположение, что он будет использовать последний зарегистрированныйподходящий провайдер.



Я что-то упустил, или есть лучший подход к выбору поставщика основываясь на теге текущей области жизненного цикла?

544   2  

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

    Ничего не найдено.