【问题标题】:What would be the most efficient way to intercept and ignore a method call on a certain condition?在特定条件下拦截和忽略方法调用的最有效方法是什么?
【发布时间】:2012-03-15 17:00:04
【问题描述】:

我有一个类Logger,其中包含许多用于各种用户活动记录的静态方法。比如:

public static class Logger
{
    public static void FileDownload(int fileId, int userId) 
    {
        // Do stuff
    }

    // ... and a number of similar additional methods
}

所以我现在想忽略为特定角色的用户记录活动。

我的想法是,为了避免重写大量代码并出于 DRY 的目的,实现一个我可以在 Logger 类上使用的自定义属性,该属性将在每个方法调用中验证是否用户处于特定角色,在这种情况下,我想完全忽略方法调用。

我无法解决的问题是如何拦截和中止我的属性中的方法调用。

是否有可能,或者是否有其他更有效的方法来拦截方法调用并在某个条件为真时忽略它?

【问题讨论】:

  • 不,C# 没有提供像 AOP 一样的 ad-hoc 方法拦截机制。
  • 这看起来是一个非常相似的问题/答案:stackoverflow.com/questions/4502134/…
  • @gymbrall 确实如此,不知道我是怎么错过的,一直在寻找。谢谢!

标签: c# .net asp.net-mvc-3 static-methods custom-attributes


【解决方案1】:

一种有效的方法和DRY 是将这些方法从static 更改为实例方法,然后从类Logger 继承并覆盖其方法以不执行任何操作。

你的Logger 类现在看起来像这样:

public class Logger
{
    public virtual void FileDownload(int fileId, int userId) 
    {
        // Do stuff
    }
    // ... and a number of similar additional methods
}

子类将如下所示:

public class IdleLogger : Logger
{
    public override void FileDownload(int fileId, int userId) 
    {
        // Do NOTHING
    }
    // ... and a number of similar additional methods
}

那么你可以说:

var myLogger =  IsUserInNoLoggingRole  ? new IdleLogger() : new Logger();

...你就完成了!简单、高效、DRY 和优雅。

【讨论】:

  • +1:根据用户的请求设置记录器。在 HttpContext.Current.Items 中缓存或使用可以配置为根据请求返回不同实例的依赖注入容器可能很有用。
  • 我喜欢这种方法。为了简单起见,我想我可以实例化记录器并将其保存在我的 SecurityContext 中。
  • 在这里的多用户环境中,这种方法不会创建更多(超过所需)的记录器实例吗?还是我错过了显而易见的事情?
【解决方案2】:

一般来说,您的日志记录应该是完整的,这取决于需要根据用户类型决定显示活动的报告应用程序。话虽如此(我相信你有充分的理由去做“if then else”),这可以通过创建一个通用的日志记录方法(logMessage)来实现

int t = User.LogRequired? logMessage(<parameters here>) : 0;

【讨论】:

    【解决方案3】:

    为什么不在实际记录任何内容之前简单地检查一下?

    public static class Logger
    {
     public void LogSensetiveInformation(string message)
     {
      if (!AllowedLogging(HttpContext.Current)
      {
        return;
      }
    
      LogMessage(message);// write message to some storage
    
     }
     public void Log(string message)
     {
      LogMessage(message);// write message to some storage
     }
    }
    

    这样您就不需要以任何特殊方式注释代码(这可能无论如何都不可能,因为所有类型的用户都可能使用相同的方法)。

    【讨论】:

    • 感谢您的回答!我想使用属性或类似属性的原因是我不必在每个方法中都进行检查。
    • 您只需要向您的记录器本身添加检查,您的常规代码将保持不变。我也更喜欢 Diego 的回答,因为它更笼统。
    猜你喜欢
    • 2011-05-28
    • 2011-02-21
    • 2021-09-16
    • 2014-10-11
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多