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, useSystem.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.