Простое Injector асинхронное определение времени жизни и исключение безопасности

У меня есть AsyncCommandHandlerDecorator<TCommand> а также LifetimeScopedCommandHandlerDecorator<TCommand> как показано ниже:

public class AsyncCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand> where TCommand : ICommand {

    private readonly Func<ICommandHandler<TCommand>> _factory;

    public AsyncCommandHandlerDecorator(Func<ICommandHandler<TCommand>> factory) {
        _factory = factory;
    }

    [SecurityCritical]
    // with or whitout SecurityCritical attribute, problem exists. 
    public void Handle(TCommand command) {
        ThreadPool.QueueUserWorkItem(_ => {
            var handler = _factory();
            handler.Handle(command);
        });
    }
}

// AND

public class LifetimeScopedCommandHandlerDecorator<TCommand>
    : ICommandHandler<TCommand> where TCommand : ICommand {

    private readonly Container _container;
    private readonly Func<ICommandHandler<TCommand>> _factory;

    public LifetimeScopedCommandHandlerDecorator(Container container,
        Func<ICommandHandler<TCommand>> factory) {
        _container = container;
        _factory = factory;
    }


    [SecurityCritical]
    // with or whitout SecurityCritical attribute, problem exists. 
    public void Handle(TCommand command) {
        using (_container.BeginLifetimeScope()) {
            var handler = _factory();
            handler.Handle(command);
        }
    }
}

и я регистрирую декораторы так:

container.RegisterSingleDecorator(
    typeof(ICommandHandler<>),
    typeof(LifetimeScopedCommandHandlerDecorator<>),
    c => c.ImplementationType.Name.StartsWith("Async"));

container.RegisterSingleDecorator(
    typeof(ICommandHandler<>),
    typeof(AsyncCommandHandlerDecorator<>),
    c => c.ImplementationType.Name.StartsWith("Async"));

Но, когда асинхронный процесс пытается вызвать, я получаю эту ошибку:

Попытка прозрачного для безопасности метода "LifetimeScopedCommandHandlerDecorator`1.Handle(!0)" для доступа к критическому методу безопасности "SimpleInjector.SimpleInjectorLifetimeScopeExtensions.BeginLifetimeScope(SimpleInjector.Container)" не удалась.

Я пытался использовать SecurityCritical атрибут на обоих LifetimeScopedCommandHandlerDecorator.Handle а также AsyncCommandHandlerDecorator.Handle, но это не помогло. Есть идеи, пожалуйста?

ОБНОВИТЬ:

Исключение имеет тип MethodAccessException и вот полная трассировка стека:

в MYNAMESPACE.LifetimeScopedCommandHandlerDecorator`1.Handle(команда TCommand)

в MYNAMESPACE.AsyncCommandHandlerDecorator`1.<> c_ DisplayClass1.b_0 (Object _)

   in C:\MYPROJECTPATH\AsyncCommandHandlerDecorator.cs:line 23 

в System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(состояние объекта)

в System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое preserveSyncCtx)

в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое preserveSyncCtx)

в System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()

в System.Threading.ThreadPoolWorkQueue.Dispatch()

в System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

ОБНОВЛЕНИЕ 2:

С или без SecurityCritical атрибут, проблема существует.

1 ответ

Решение

Наконец, я нашел ответ (спасибо @Steven за его помощь). В свою сборку я добавил [SecurityTransparent] по некоторым причинам. С другой стороны, Simple Injector использует ThreadLocal<T> внутренне. И ThreadLocal<T> приписывается HostProtection(SecurityAction.LinkDemand) И в LinkDemand Комментарий, мы можем прочитать:

Непосредственный абонент должен получить указанное разрешение. Не используйте в.NET Framework 4. Для полного использования доверия System.Security.SecurityCriticalAttribute вместо; для частичного доверия используйте System.Security.Permissions.SecurityAction.Demand,

Это означает, что на самом деле ThreadLocal<T> класс SecurityCritical объект, и мы не можем назвать SecurityCritical метод по SecurityTransparent один.

Другие вопросы по тегам