AOP with Roslyn–part 2
I want to transform code by injecting some simple code, like “Console.WriteLine(“method”)
So this code:
using System; namespace Test1 { class Program { static void Main(string[] args) { var dt=DateTime.Now; } } }
should be modified to this code:
using System; namespace Test1 { class Program { static void Main(string[] args) { Console.WriteLine(" + "\"Program_Main_6\"" + @");//this is automatically added var dt = DateTime.Now; } } }
How I do the code: I derive from CSharpSyntaxRewriter and override the VisitMethodDeclaration . I will construct a new node with the Console.WriteLine statement inserted
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { if (node.Body == null || node.Body.Statements.Count == 0) return base.VisitMethodDeclaration(node); var parent = node.Parent as ClassDeclarationSyntax; if (parent == null) return base.VisitMethodDeclaration(node); var nameMethod = node.Identifier.Text; var nameClass = parent.Identifier.Text; Console.WriteLine(nameMethod); node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); var lineStart = node.GetLocation().GetLineSpan().StartLinePosition; string nameVariable = $"{nameClass}_{nameMethod}_{lineStart.Line}"; var cmd = SyntaxFactory.ParseStatement($"Console.WriteLine(\"{nameVariable}\");//this is automatically added"); var blockWithNewStatements = new SyntaxList<StatementSyntax>(); for (int i = node.Body.Statements.Count - 1; i >= 0; i--) { var st = node.Body.Statements[i]; blockWithNewStatements = blockWithNewStatements.Insert(0, st); } blockWithNewStatements = blockWithNewStatements.Insert(0, cmd); var newBlock = SyntaxFactory.Block(blockWithNewStatements); var newMethod = SyntaxFactory.MethodDeclaration (node.AttributeLists, node.Modifiers, node.ReturnType, node.ExplicitInterfaceSpecifier, node.Identifier, node.TypeParameterList, node.ParameterList, node.ConstraintClauses, newBlock, node.ExpressionBody, node.SemicolonToken); var newNode = node.ReplaceNode(node, newMethod); return base.VisitMethodDeclaration(newNode); }
As test, I have created a TestMethodRewriterSimple that verifies that.
[TestMethod] public void TestMethodRewriterSimple() { var rc = new RewriteCode(); rc.Code = @" using System; namespace Test1 { class Program { static void Main(string[] args) { var dt=DateTime.Now; } } }"; var result= rc.RewriteCodeMethod(); var newCode = @" using System; namespace Test1 { class Program { static void Main(string[] args) { Console.WriteLine(" + "\"Program_Main_6\"" + @");//this is automatically added var dt = DateTime.Now; } } }"; Assert.AreEqual(newCode.Replace(Environment.NewLine,""), newCode.Replace(Environment.NewLine, "")); } }
You can find the code on https://github.com/ignatandrei/AOP_With_Roslyn
Leave a Reply