我有一个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"));
但是,当异步进程尝试调用时,我会得到以下错误:
通过安全透明方法进行的尝试'LifetimeScopedCommandHandlerRecorder`1.Handle(!0)'到访问安全关键方法"SimpleInjector.SimpleInjectorLifetimeScopeExtensions.BeginLifetimeScope(SimpleInjecter.Container)"失败。
我尝试在LifetimeScopedCommandHandlerDecorator.Handle
和AsyncCommandHandlerDecorator.Handle
上使用SecurityCritical
属性,但没有帮助。你知道吗?
更新:
异常类型为MethodAccessException
,这里是完整的堆栈跟踪:
位于MYNAMESPACE.AncCommandHandlerRecorder`1.<>c_DisplayClass1.b_0(对象_)
in C:MYPROJECTPATHAsyncCommandHandlerDecorator.cs:line 23
位于System.Threading.QueueUserWorkItemCallback.WetCallback_Context(对象状态)
在System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext,ContextCallback回调,Object state,Boolean preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,Object state,Boolean preserveSyncCtx)
位于System.Threading.QueueUserWorkItemCallback.System.ThreadPoolWorkItem.ExecuteWorkItem()
位于System.Threading.ThreadPoolWorkQueue.Dispatch()
位于System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
更新2:
有或没有SecurityCritical
属性,则存在问题。
终于找到了答案(感谢@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
对象,并且我们不能用SecurityTransparent
方法来调用SecurityCritical
。