C# 让PostSharp帮助记录IF语句

C# 让PostSharp帮助记录IF语句,c#,aop,postsharp,C#,Aop,Postsharp,我要寻找的行为如下所示: [IfElseLogging] public void Foo(string bar) { if (bar == "somedumbstringbecausethisishorriblewayofdoingthings") { // here the aspect would log that the if statement above was true, // and thus took this path }

我要寻找的行为如下所示:

[IfElseLogging]
public void Foo(string bar)
{
    if (bar == "somedumbstringbecausethisishorriblewayofdoingthings")
    {
        // here the aspect would log that the if statement above was true,
        // and thus took this path
    }
    else
    {
        // here the aspect would log that the if statement above was false,
        // and thus took this path
    }
}
如果有办法劫持
If
功能,我就可以用Postsharp使用的日志来装饰它,并从我的手上掸去灰尘。我补充这个问题的另一个原因是我不确定我问的是什么

这是一个由一个非常年轻的开发人员完成的项目。我的任务不仅仅是重构,而是记录代码在流程图级别上的具体操作。考虑到代码的性质、缺乏描述、技术和实践差、项目的性质等。。。以下是我正在努力解决的问题:

  • 我不能简单地在本地调试和单步执行代码
  • 我无法安全地创建单元测试和重构
  • 我不明白这个代码是做什么的
  • 我没有原始的需求文档来理解功能的目标是什么
因此,我希望使用Postsharp基本上为我提供代码路径和单元测试标准,因为我不知道如何获得它


从另一个角度考虑,是否可能有一个方面在发现if语句时触发事件?

您应该继承
onmethodboundaryapect
并重写
OnEntry(MethodExecutionArgs args)
onexceptionspect
并重写
OnException(MethodExecutionArgs args)
。您可以从args中获取并比较
字符串条

面向方面编程与PostSharp将允许您创建拦截器,这些拦截器在定义良好的点(如方法调用和属性访问)连接到您的代码中。这是通过重写源代码生成的IL来完成的

在您的情况下,您正在寻找特定的
if
语句,但它们在生成的IL中不容易识别。以下是为示例方法生成的内容:

nop ldarg.1 ldstr "somedumbstringbecausethisishorriblewayofdoingthings" call System.String.op_Equality stloc.0 ldloc.0 brfalse.s NotEqual nop **True branch** br.s Return NotEqual: nop **False branch** Return: ret 插入检测代码
System.Console.WriteLine(“真分支”)使用了以下相当复杂的方法:

IEnumerable<StatementSyntax> CreateInstrumentationStatements(String text) {
  return SyntaxFactory.SingletonList<StatementSyntax>(
    SyntaxFactory.ExpressionStatement(
      SyntaxFactory.InvocationExpression(
        SyntaxFactory.MemberAccessExpression(
          SyntaxKind.SimpleMemberAccessExpression,
          SyntaxFactory.MemberAccessExpression(
            SyntaxKind.SimpleMemberAccessExpression,
            SyntaxFactory.IdentifierName("System"),
            SyntaxFactory.IdentifierName("Console")
          )
          .WithOperatorToken(SyntaxFactory.Token(SyntaxKind.DotToken)),
          SyntaxFactory.IdentifierName("WriteLine")
        )
        .WithOperatorToken(SyntaxFactory.Token(SyntaxKind.DotToken))
      )
      .WithArgumentList(
        SyntaxFactory.ArgumentList(
          SyntaxFactory.SeparatedList(
            new[] {
              SyntaxFactory.Argument(
                SyntaxFactory.LiteralExpression(
                  SyntaxKind.StringLiteralExpression,
                  SyntaxFactory.Literal(text)
                )
              )
            }
          )
        )
      )
    )
    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
  );
}

您需要大量扩展代码,以便更好地过滤
if
语句,并处理可以编写
if
语句的所有不同方式,但与IL重写相比,这应该会给您带来更高的成功几率。

这不是我想要的,很可能是我对这就是问题所在。。。我需要的是记录代码通过“if”语句的路径。这个例子过于简单化了。我正在处理由一个非常jr的开发人员编写的遗留代码,我需要知道它是如何工作的,由于它的复杂性,加上幻数和其他类似比较的糟糕编码实践,以及无法在本地调试代码的处理。。。并且必须为客户记录代码的实际功能。。。我正在寻找可以表示代码路径的日志。。。如果我有更多的信息,我会从那里创建单元测试和重构。。。但考虑到目前的情况,这不太可行。我知道。这是一个关键词。。。因此,我无法覆盖它的功能谢谢你的解释,这正是我想要的!
class IfStatementRewriter : CSharpSyntaxRewriter {

  public override SyntaxNode VisitIfStatement(IfStatementSyntax ifStatement) {
    var containsMagicString = ifStatement
      .Condition
      .DescendantNodes()
      .Any(
        syntaxNode => syntaxNode.ToString() == @"""somedumbstringbecausethisishorriblewayofdoingthings"""
      );
    if (!containsMagicString)
      // Do not modify if statement.
      return ifStatement;
    // Only look at the "true" part and assume it is a block (has curly braces).
    var block = ifStatement.Statement as BlockSyntax;
    if (block == null)
      // Do not modify if statement.
      return ifStatement;
    // Insert instrumentation code at start of block.
    var instrumentationStatements = CreateInstrumentationStatements("True branch");
    var modifiedStatements = block.Statements.InsertRange(0, instrumentationStatements);
    var modifiedBlock = block.WithStatements(modifiedStatements);
    return ifStatement.WithStatement(modifiedBlock);
  }

}
IEnumerable<StatementSyntax> CreateInstrumentationStatements(String text) {
  return SyntaxFactory.SingletonList<StatementSyntax>(
    SyntaxFactory.ExpressionStatement(
      SyntaxFactory.InvocationExpression(
        SyntaxFactory.MemberAccessExpression(
          SyntaxKind.SimpleMemberAccessExpression,
          SyntaxFactory.MemberAccessExpression(
            SyntaxKind.SimpleMemberAccessExpression,
            SyntaxFactory.IdentifierName("System"),
            SyntaxFactory.IdentifierName("Console")
          )
          .WithOperatorToken(SyntaxFactory.Token(SyntaxKind.DotToken)),
          SyntaxFactory.IdentifierName("WriteLine")
        )
        .WithOperatorToken(SyntaxFactory.Token(SyntaxKind.DotToken))
      )
      .WithArgumentList(
        SyntaxFactory.ArgumentList(
          SyntaxFactory.SeparatedList(
            new[] {
              SyntaxFactory.Argument(
                SyntaxFactory.LiteralExpression(
                  SyntaxKind.StringLiteralExpression,
                  SyntaxFactory.Literal(text)
                )
              )
            }
          )
        )
      )
    )
    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
  );
}
var root = (CompilationUnitSyntax) syntaxTree.GetRoot();
var rewriter = new IfStatementRewriter();
var rewrittenRoot = rewriter.Visit(root);