Простое 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
один.