I have a AsyncCommandHandlerDecorator<TCommand> and LifetimeScopedCommandHandlerDecorator<TCommand> as shown below:

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);
        }
    }
}

and I register decorators like this:

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

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

But, when the async process attempt to invoke, I get this error:

Attempt by security transparent method 'LifetimeScopedCommandHandlerDecorator`1.Handle(!0)' to access security critical method 'SimpleInjector.SimpleInjectorLifetimeScopeExtensions.BeginLifetimeScope(SimpleInjector.Container)' failed.

I tried to use SecurityCritical attribute on both LifetimeScopedCommandHandlerDecorator.Handle and AsyncCommandHandlerDecorator.Handle, but it didn't help. Have you any idea please?

UPDATE:

The exception is of type MethodAccessException and here is the complete stack trace:

at MYNAMESPACE.LifetimeScopedCommandHandlerDecorator`1.Handle(TCommand command)

at MYNAMESPACE.AsyncCommandHandlerDecorator`1.<>c_DisplayClass1.b_0(Object _)

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

at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)

at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)

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

at System.Threading.ThreadPoolWorkQueue.Dispatch()

at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

UPDATE 2:

With or whitout SecurityCritical attribute, problem exists.

有帮助吗?

解决方案

Finally, I found the answer (thanks to @Steven for his helps). In my assembly, I have added [SecurityTransparent] for some reasons. In the other hand, Simple Injector uses the ThreadLocal<T> internally. And the ThreadLocal<T> is attributed by HostProtection(SecurityAction.LinkDemand) and in LinkDemand's comment, we can read:

The immediate caller is required to have been granted the specified permission. Do not use in the .NET framework 4. For full trust use System.Security.SecurityCriticalAttribute instead; for partial trust, use System.Security.Permissions.SecurityAction.Demand.

That means actually the ThreadLocal<T> class is a SecurityCritical object and we can not call a SecurityCritical method by a SecurityTransparent one.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top