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使用的日志来装饰它,并从我的手上掸去灰尘。我补充这个问题的另一个原因是我不确定我问的是什么
这是一个由一个非常年轻的开发人员完成的项目。我的任务不仅仅是重构,而是记录代码在流程图级别上的具体操作。考虑到代码的性质、缺乏描述、技术和实践差、项目的性质等。。。以下是我正在努力解决的问题:
- 我不能简单地在本地调试和单步执行代码
- 我无法安全地创建单元测试和重构
- 我不明白这个代码是做什么的李>
- 我没有原始的需求文档来理解功能的目标是什么
从另一个角度考虑,是否可能有一个方面在发现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);