0

После того как я начал использовать DI в фильтрах я получаю следующий EF исключение:Новый экземпляр IAuthorizationFilter для каждого запроса

Вторая операция началась в связи с этим перед предыдущей асинхронной операции завершена. Используйте «ждут», чтобы убедиться, что какие-либо асинхронные операции были выполнены до вызова другого метода в этом контексте. Любые члены экземпляра не гарантируют безопасность потоков.

Я использую Unity в качестве контейнера IoC. Моя установка выглядит следующим образом:

config.DependencyResolver = new UnityHierarchicalDependencyResolver(container); 

var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList(); 

//adding IFilterProvider provided by Unity 
GlobalConfiguration.Configuration.Services.Add(
    typeof(IFilterProvider), 
    new UnityActionFilterProvider(UnityConfig.GetConfiguredContainer())); 

var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider); 

//removing default IFilterProvider 
GlobalConfiguration.Configuration.Services.Remove(
    typeof(IFilterProvider), 
    defaultprovider); 

Тогда я регистрирующий мой фильтр для авторизации, как это:

var authFilter = config.DependencyResolver.GetService(typeof(MyFilterType)); 
config.Filters.Add((MyFilterType)authFilter); 

Мой фильтр авторизации выглядит следующим образом:

public class MyFilterType : IAuthorizationFilter 
{ 
    private readonly MyServiceInterfaceType _service; 

    public MyFilterType(MyServiceInterfaceType service) 
    { 
     _service = service; 
    } 

    public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, 
     CancellationToken cancellationToken, 
     Func<Task<HttpResponseMessage>> continuation) 
    { 
     var res = await _service.SomeAction(); 

     //the rest doesn't matter 
    } 
} 

MyServiceInterfaceType внутри агрегатов MyRepositoryInterfaceType , Так что это просто обычный шаблон Service-Repository. Внутри MyRepositoryInterfaceType Инициализируется контекст EF.

Итак, об исключении. Я знаю, что это значит - есть параллельные асинхронные вызовы контекста. Я думаю, что это из-за этих двух строк:

var authFilter = config.DependencyResolver.GetService(typeof(MyFilterType)); 
config.Filters.Add((MyFilterType)authFilter); 

Экземпляр фильтра хранится, в основном, одноэлементным. Таким образом, каждый вызов фильтра обслуживается одним и тем же экземпляром контекста EF, поэтому есть исключения.

(Пожалуйста, поправьте меня, если я где-то не так с этим.)

Мой вопрос: Можно ли создать новый экземпляр моего MyFilterType фильтра для каждого вызова, чтобы избежать этих исключений?

ответ

1

Вам нужно будет сделать сервисное местоположение внутри вашего метода.

var requestScope = actionContext.Request.GetDependencyScope(); 
var myService = requestScope.GetService(MyServiceInterfaceType) as MyServiceInterfaceType; 

Autofac имеет свои собственные фильтры, которые можно использовать, если вы использовали его вместо единства, но я не думаю, что Unity предлагает ничего подобного. Документы Autofac обеспечивают довольно хорошее объяснение ситуации: http://docs.autofac.org/en/latest/integration/webapi.html#provide-filters-via-dependency-injection

Смежные вопросы