Асинхронная область действия простого инжектора и исключение безопасности

У меня есть 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, и вот полная трассировка стека:

at 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 ExecutionContext, обратный вызов ContextCallback, состояние объекта, логическое значение saveSyncCtx)

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

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

в System.Threading.ThreadPoolWorkQueue.Dispatch()

в System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

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

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


person amiry jd    schedule 24.11.2012    source источник
comment
Можете ли вы предоставить тип исключения и полную трассировку стека.   -  person Steven    schedule 24.11.2012
comment
@Стивен, да, я обновляю Q и добавляю тип исключения и полную трассировку стека. Благодаря вашей помощи.   -  person amiry jd    schedule 24.11.2012
comment
Зачем вам атрибуты [SecurityCritical]? Без них проблема не исчезнет?   -  person Steven    schedule 24.11.2012
comment
@Стивен Нет. Я поставил этот атрибут после того, как у меня возникла проблема. Я погуглил ошибку и нашел несколько статей, в которых говорилось, что когда прозрачный метод безопасности вызывает критический с точки зрения безопасности, одним из способов решения проблемы является создание прозрачного метода безопасности SecurityCritical. С ними или без них, разницы никакой.   -  person amiry jd    schedule 24.11.2012
comment
Вот одна из статей, которые я нашел: msdn.microsoft.com/en-us/ библиотека/bb264475.aspx   -  person amiry jd    schedule 24.11.2012
comment
@Стивен, какой результат? любое предложение? Я ищу, но пока безрезультатно :( Я видел исходник на codeplex; Но на BeginLifetimeScope нет атрибута SecurityCritical. Итак, почему эта ошибка возникает? Есть идеи?   -  person amiry jd    schedule 24.11.2012
comment
Вы работаете в частичном доверии?   -  person Steven    schedule 25.11.2012
comment
@ Стивен, да, я использовал его с частичным доверием. Но теперь я работаю в полном доверии, и проблема решена. Я использую MVC 4, .NET 4.5, Win 7, IIS Express 8, VS 2012. При полном доверии проблем нет.   -  person amiry jd    schedule 25.11.2012


Ответы (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. .

person amiry jd    schedule 29.11.2012