如何转换:
System.Linq.Expression.Expression
进入:
Microsoft.CodeAnalysis.CSharp.CSharpCompilation
或进入:
Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree
我需要下一个具体的案例,就像一个选择:
我可以将
Expression
和CSharpSyntaxTree
编译为可执行代码的相同行为当我查看手动输入的c表达式时,我可以得到
CSharpSyntaxTree
,它将生成相同的代码。public void MultipleStatementsBlockTest()
{
var p = Expression.Parameter(typeof(int), "p");
Expression assignment = Expression.Assign(p, Expression.Constant(1));
Expression addAssignment = Expression.AddAssign(p, Expression.Constant(5));
// Convert addAssignment to Roslyn tree here
}
class HasIndexers
{
public object this[string s] => null;
public object this[int i] => null;
}
public void CanPrettyPrintVariousIndexers()
{
Expression<Func<Bool>> expr = () => new HasIndexers()[3] == new HasIndexers()["three"];
// Convert expr to Roslyn tree here
}
更新:
接近
Expression -> string -> Roslyn
不可接受。转换应该是直接的。更新2:
可能的用途:
基于运行时表达式的di/ioc容器或orm或消息总线或其他库进入编译时库并生成代码。
A.快速启动
编译时错误,而不是运行时错误。
可能更快的运行时间。
通过吃馅饼,让C长寿。
可能是更多的混合库,例如矩阵(图像)操作,允许复制和粘贴在服务器/桌面上创建的结果树,作为在物联网上使用的代码。
表达式库(例如,用于调试),用于将它们转换为C代码。
更多的代码输出选项(名称空间,空格,制表符)。
b.正确性更高,生成的人工代码更少。
c.支持不同的输出语言,而不是c。
最佳答案
见here syntax transformation
由于语法树是不可变的,Syntax API没有提供直接机制来修改构造后的现有语法树。但是,语法API确实提供了基于对已有树的指定更改生成新树的方法。从syntaxnode派生的每个具体类都使用*方法定义,您可以使用这些方法指定对其子属性的更改。
此外,replace node扩展方法可用于替换子树中的子节点。如果不使用此方法更新节点,则还需要手动更新其父节点以指向新创建的子节点,并在整个树上重复此过程
被称为重新旋转树的过程。
示例-使用with*和replacenode方法的转换:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace ConstructionCS
{
class Program
{
static void Main(string[] args)
{
NameSyntax name = IdentifierName("System");
name = QualifiedName(name, IdentifierName("Collections"));
name = QualifiedName(name, IdentifierName("Generic"));
SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}");
var root = (CompilationUnitSyntax)tree.GetRoot();
var oldUsing = root.Usings[1];
var newUsing = oldUsing.WithName(name);
root = root.ReplaceNode(oldUsing, newUsing);
}
}
}
现场试用:http://roslynquoter.azurewebsites.net/