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