3

我正在编写一个审计日志系统以集成到现有的软件中,并且数据库结构包括一个字段,用于记录有关正在记录的操作的详细信息。不必花哨;它不需要太多,当它需要时,在大多数情况下,开发人员会读取它以找出调用了哪个方法以及使用了哪些参数,诸如此类。这意味着虽然它应该是人类可读的,但它不需要被任何东西解析。因此,与其有很多重载,或者使用可怕的 switch case 字符串替换,我想一个写细节 blob 的好方法是进行日志调用,以获取正在记录的操作所需的参数的名称,以及值传递给他们的。我做了一些研究,

这是我所追求的粗略模拟:

Dictionary<string,string> parameters = new Dictionary<string,string>();
foreach (Parameter p in MethodCall)
{
    parameters.Add(p.Name, p.Value.ToString());
}

LogEvent(EventType.Something, userID = thisUser, details = parameters);

我知道它可能比实践中的更复杂,但它为您提供了总体思路。在我的 LogEvent 方法中,有一些东西可以添加时间戳,为用户端日志查看器构建描述性句子(技术细节比我们向管理员和开发人员展示的要少,以免暴露我们的程序/数据库结构)和 - 理论上 - 构建参数详细信息字典中的某种 blob(可能是 JSON 或类似的)。

4

4 回答 4

1

我将使用拦截器(Castle.DynamicProxy),如下面的示例所示:

  internal class Program
  {
    private static void Main(string[] args)
    {

      var interceptor = new Interceptor();
      var businessObjectClass = new ProxyGenerator().CreateInterfaceProxyWithoutTarget<IBusinessObjectClass>(interceptor);

      businessObjectClass.Method3("what",123);

      Console.ReadLine();
    }
  }

  public class Interceptor : IInterceptor
  {
    #region IInterceptor Members

    public void Intercept(IInvocation invocation)
    {
      Console.WriteLine(string.Format("Intercepted call to: " + invocation.Method.Name));
      foreach (var argument in invocation.Arguments)
      {
        Console.WriteLine(string.Format("\t Param: " + argument.ToString()));
      }
      invocation.Proceed();
    }

    #endregion
  }

  public interface IBusinessObjectClass
  {
    void Method3(string stringValue, int intValue);
  }

  public class BusinessObjectClass : IBusinessObjectClass
  {

     public void Method3(string stringValue, int intValue)
    {
      return;
     }

  }

动态代理

于 2012-11-06T14:32:03.997 回答
1

如果您的日志记录方法采用表达式参数,则可以通过以下代码获取参数名称和值:

static void LogSomething(Expression<Action> expression)
{
    var methodCallExpression = ((MethodCallExpression) expression.Body);
    var parameterNames = methodCallExpression.Method.GetParameters().Select(p => p.Name);
    var values = methodCallExpression.Arguments.Select(a => a.Value);
}
于 2012-11-06T13:27:31.913 回答
1

相关内容是:从 .NET 中的堆栈帧获取参数值?其中有一些有用的答案。

您想要记录方法名称和参数列表。方法名称很容易使用 StackFrame,但我认为您不能使用简单的反射来获取参数值。

于 2012-11-06T13:14:11.283 回答
0

你为什么不试试PostSharp?它旨在解决像您这样的问题。在示例中,您将找到打印参数值的日志记录方面。结合 XML 配置,将允许管理员/用户随意启用日志记录/跟踪。

于 2012-11-09T22:18:51.597 回答