我正在寻找的行为如下:
[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使用的日志记录来装饰它并从我的手上除去灰尘。我加入问题的另一个原因是我不确定我是否清楚我要问的是什么。
这是一个由Jr开发人员完成的项目。我的任务不仅仅是重构,而是记录代码对流程图级别的确切作用。鉴于代码的性质,缺乏描述,糟糕的技术和实践,项目的性质等等......以下是我正在努力解决的问题:
所以我希望使用Postsharp来基本上给我我的代码路径和单元测试标准,因为我不知道如何获得它。
另一个想法是,是否有可能在找到if语句时触发事件的方面?
答案 0 :(得分:2)
使用PostSharp进行面向方面编程将允许您创建拦截器,这些拦截器会在方法调用和属性访问等明确定义的点处挂钩您的代码。这样做就是重写从源代码生成的IL。
在您的情况下,您正在寻找特定的 <Charting:Chart.Series>
<Charting:PieSeries x:Name="MySeries" Title="Population" IndependentValueBinding="{Binding Name}" DependentValueBinding="{Binding Amount}" IsSelectionEnabled="False" Width="125" Height="125" />
</Charting:Chart.Series>
<ControlTemplate TargetType="series:LegendItem">
<StackPanel Orientation="Horizontal">
<datavis:Title Content="{TemplateBinding Content}" />
<TextBlock Text="{Binding DependentValueBinding, ElementName=MySeries}" />
</StackPanel>
</ControlTemplate>
语句,但在生成的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
但是,这是非优化版本。优化编译器生成此代码:
ldarg.1 ldstr "somedumbstringbecausethisishorriblewayofdoingthings" call System.String.op_Equality brfalse.s NotEqual **True branch** ret NotEqual: **False branch** ret
因此,如果你想进行IL重写,可以想象拦截方法调用,寻找类似于if
的IL签名,然后重写IL来修改代码。但是,这种方法非常脆弱。源代码中的细微差别可能会生成具有不同签名的IL,并且只有编译器编写者才能真正了解您所查找的整个IL签名范围。如果条件语句涉及与逻辑运算符结合的多个术语,那么确定插入检测代码的位置会变得非常复杂。然后有误报。就个人而言,我认为这不是一个可行的策略来检测你的代码。
但是,您有另一种选择。您可以使用Roslyn编译源代码并使用Roslyn重写器来修改原始源代码树。这是源级别的AOP,而不是在IL级别提供AOP的PostSharp。
要重写语法树,您需要从ldstr, "...", call System.String.op_Equality, brfalse.s
派生一个类。此重写器将修改CSharpSyntaxRewriter
语句,以便覆盖if
方法:
VisitIfStatement
要插入检测代码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);
}
}
,使用以下相当有毛的方法:
System.Console.WriteLine("True branch");
您现在可以修改语法树:
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);
语句并处理if
语句的所有不同方式,但与进行IL重写相比,这应该会让您更高成功的机会。
答案 1 :(得分:0)
您应该继承import pandas as pd
aframe = pd.read_csv('thefile.csv')
Out[19]:
Name Value Value2 Value3 Rating
0 ddf 34 45 46 ok
1 ddf 67 23 11 ok
2 ghd 23 11 78 bad
3 ghd 56 33 78 bad
r = aframe.groupby(['Name','Rating'],as_index=False).sum()
Out[40]:
Name Rating Value Value2 Value3
0 ddf ok 101 68 57
1 ghd bad 79 44 156
并覆盖OnMethodBoundaryAspect
或OnEntry(MethodExecutionArgs args)
并覆盖OnExceptionAspect
。您可以从args
OnException(MethodExecutionArgs args)