我有一个 AOP 审计库,它拦截使用 Castle DynamicProxy 和 Autofac 的方法,并检查它们是否具有此特定属性:
[Audit(AuditOperation.Create), MethodImpl(MethodImplOptions.NoInlining)]
public virtual TEntity Add(TEntity entity, [MethodIsAuditableParam]bool methodIsAuditable = true)
{
entity = entity.DeleteNestedProperties();
using (var entityContext = ContextCreator())
{
TEntity addedEntity = entityContext.Set<TEntity>().Add(entity);
entityContext.SaveChanges();
return addedEntity;
}
}
这是一种将通用实体添加到数据库的通用存储库方法。但是我在我的域层中也有特定的方法来做额外的事情,然后调用这些通用的存储库方法:
[Audit(AuditOperation.Create), MethodImpl(MethodImplOptions.NoInlining)]
public virtual User AddUser(int currentUserId, User newUser, [MethodIsAuditableParam]bool methodIsAuditable = true)
{
try
{
UserDBValidations(currentUserId, newUser);
if (newUser.UserProfileId == (int)UserProfileType.Admin ||
newUser.UserProfileId == (int)UserProfileType.ProcessSpecialist)
newUser.UGBs = _ugbRepository.FindAll().ToList();
_userRepository.Add(newUser);
return newUser;
}
catch (Exception ex)
{
throw new Exception("Erro no cadastro de usuário: " + ex.Message);
}
}
我的意图是,如果存在可审计的域方法(可以调用许多通用存储库方法),我的审计拦截器将仅审计此域方法,并将忽略通用存储库审计。但是如果我直接调用通用存储库方法,它们将被正常审计。
我尝试使用拦截器中的堆栈跟踪来实现此行为。以下方法检查堆栈帧数组是否已包含IInterceptor.Intercept方法。:
private bool CheckIfMethodCallersAreBeingIntercepted()
{
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
//the int number should match the exact number of method calls in this interception until this current method
StackFrame[] realStackFrames = stackFrames.SubArray(5, stackFrames.Count() - 5);
foreach (StackFrame realStackFrame in realStackFrames)
{
MethodBase method = realStackFrame.GetMethod();
if (method == null)
continue;
Type declaringType = method.DeclaringType;
if (declaringType == null)
continue;
string declaringTypeFullName = declaringType.FullName;
if (declaringTypeFullName == null)
continue;
if(declaringTypeFullName
.Contains("AwesomeAuditing.AwesomeAuditingInterceptor"))
return true;
}
return false;
}
但这不起作用,因为我可以拦截一个方法而不审计它:
public void Intercept(IInvocation invocation)
{
if (!CheckIfMethodShouldBeIntercepted(invocation.Method, invocation.Arguments))
{
invocation.Proceed();
return;
}
if (!CheckIfMethodReturnTypeInheritAuditEntity(invocation.Method))
throw new AwesomeAuditingException(@"The audited method's return type most inherit the IAuditableEntity interface.");
invocation.Proceed();
if (CheckIfMethodIsAsync(invocation.Method))
invocation.ReturnValue = AsyncProceedExecution((dynamic)invocation.ReturnValue, invocation);
else
AfterProceedExecution(invocation.ReturnValue, invocation);
}
我不想使用所有当前拦截的方法来管理静态集合,因为我希望这个 AOP 库可以处理多种类型的项目(Web API、Windows 服务、控制台应用程序、WPF 等),并且每种类型都有自己的方式管理静态实例。例如,在 Web API 上下文中,我不希望两个 HTTP 请求共享此静态集合。在 Windows 服务中,我不想在两个执行线程之间共享这个静态集合。
你们知道管理这种多级拦截的更好方法吗?您是否知道任何可以在许多项目类型中发挥良好作用的良好实践?