gpt4 book ai didi

c# - 解析 C# 代码(作为字符串)并插入其他方法

转载 作者:可可西里 更新时间:2023-11-01 08:43:13 24 4
gpt4 key购买 nike

我有一个正在开发的 C# 应用程序,它可以远程加载它的代码,然后运行它(为了论证,您可以假设该应用程序是安全的)。

代码是 C#,但它作为 XML 文档发送,解析为字符串,然后编译和执行。

现在,我想做的 - 比我预期的要困难一些 - 能够解析整个文档,并在编译之前,在每行执行后插入额外的命令。

例如,考虑以下代码:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCode
{
static class MyProg
{
static void Run()
{
int i = 0;
i++;

Log(i);
}
}
}

我想要的,在解析之后更像是:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCode
{
static class MyProg
{
static void Run()
{
int i = 0;
MyAdditionalMethod();
i++;
MyAdditionalMethod();

Log(i);
MyAdditionalMethod();
}
}
}

请记住明显的陷阱 - 我不能在每个分号之后都使用它,因为这在 getter/setter 中不起作用,即:

转换:

public string MyString { get; set; }

收件人:

public string MyString { get; MyAdditionalMethod(); set; MyAdditionalMethod(); }

会失败。就像类级声明、using 语句等一样。此外,在许多情况下,我还可以在花括号后添加 MyAdditionalMethod() - 比如在委托(delegate)中,紧接在 if 语句或方法声明等之后。

所以,我一直在研究 CodeDOM,这看起来可能是一个解决方案,但很难弄清楚从哪里开始。否则我会尝试解析整个事物并创建一棵我可以解析的树 - 尽管考虑到我需要考虑的案例数量,这有点困难。

有人知道其他解决方案吗?

最佳答案

我建议使用一些来自 Mono 或 SharpDevelop 的 C# 解析器,因为它们应该是最新的。我试了一下 NRefactory来自 SharpDevelop,如果你 download SharpDevelop 的源代码有一个演示和一些单元测试,可以很好地介绍它的用法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory;
using System.IO;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.NRefactory.PrettyPrinter;

namespace Parse
{
class Program
{
static void Main(string[] args)
{
string code = @"using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCode
{
static class MyProg
{
static void Run()
{
int i = 0;
i++;

Log(i);
}
}
}
";

IParser p = ParserFactory.CreateParser(SupportedLanguage.CSharp, new StringReader(code));
p.Parse();

//Output Original
CSharpOutputVisitor output = new CSharpOutputVisitor();
output.VisitCompilationUnit(p.CompilationUnit, null);
Console.Write(output.Text);

//Add custom method calls
AddMethodVisitor v = new AddMethodVisitor();
v.VisitCompilationUnit(p.CompilationUnit, null);
v.AddMethodCalls();
output = new CSharpOutputVisitor();
output.VisitCompilationUnit(p.CompilationUnit, null);

//Output result
Console.Write(output.Text);
Console.ReadLine();
}


}

//The vistor adds method calls after visiting by storing the nodes in a dictionary.
public class AddMethodVisitor : ConvertVisitorBase
{
private IdentifierExpression member = new IdentifierExpression("MyAdditionalMethod");

private Dictionary<INode, INode> expressions = new Dictionary<INode, INode>();

private void AddNode(INode original)
{
expressions.Add(original, new ExpressionStatement(new InvocationExpression(member)));
}

public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
AddNode(expressionStatement);
return base.VisitExpressionStatement(expressionStatement, data);
}

public override object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data)
{
AddNode(localVariableDeclaration);
return base.VisitLocalVariableDeclaration(localVariableDeclaration, data);
}

public void AddMethodCalls()
{
foreach (var e in expressions)
{
InsertAfterSibling(e.Key, e.Value);
}
}

}
}

您将需要改进访问者以处理更多情况,但这是一个好的开始。

或者,您可以编译原始文件并使用 Cecil 进行一些 IL 操作。或者试试像 PostSharp 这样的 AOP 库.最后你可以看看 .NET Profiling API .

关于c# - 解析 C# 代码(作为字符串)并插入其他方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4998608/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com