1

我有一个 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 服务中,我不想在两个执行线程之间共享这个静态集合。

你们知道管理这种多级拦截的更好方法吗?您是否知道任何可以在许多项目类型中发挥良好作用的良好实践?

4

0 回答 0