如何将Expression转换为CSharpCompilation或CSharpSyntaxTree?

Dzm*_*oda 8 .net c# roslyn

如何转换:

System.Linq.Expression.Expression
Run Code Online (Sandbox Code Playgroud)

成:

Microsoft.CodeAnalysis.CSharp.CSharpCompilation
Run Code Online (Sandbox Code Playgroud)

或者进入:

Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree
Run Code Online (Sandbox Code Playgroud)

我需要下一个具体案例才能像其中一个选项一样工作:

  • 我可以编译ExpressionCSharpSyntaxTree执行可执行代码的相同行为

  • 当我看到手动输入的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
    }
    
    Run Code Online (Sandbox Code Playgroud)

更新:

接近Expression -> string -> Roslyn不可接受.转换应该是直接的.

更新2:可能的用法:

  1. DI/IoC容器或ORM或消息总线或其他库基于运行时表达式进入编译时库,代码生成.

一个.开始更快

湾 编译时间错误,而不是运行时错误.

C.可能更快的运行时间.

d.吃F#馅饼让C#活得更长寿.

即 可能更多的混合库,例如用于矩阵(图像)操作,其允许复制和粘贴在服务器/桌面上创建的结果树作为要在IoT上使用的代码.

  1. 表达式lib(例如用于调试),它将这些转换为C#代码.

一个.更多代码输出选项(名称空间,空格,制表符).湾 使用较少的手动代码生成更正确.C.支持不同的输出语言而不是C#.

小智 5

请参阅此处语法转换

由于语法树是不可变的,因此语法 API不提供在构建后修改现有语法树的直接机制。然而,语法 API 确实提供了根据对现有树的指定更改生成新树的方法。从 SyntaxNode 派生的每个具体类都定义了 With* 方法,您可以使用这些方法指定对其子属性的更改。

此外,ReplaceNode 扩展方法可用于替换子树中的后代节点。如果没有这种方法,更新节点还需要手动更新其父节点以指向新创建的子节点,并在整个树上重复此过程

  • 这个过程被称为重新旋转树。

示例 - 使用 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现场试用: http: //roslynquoter.azurewebsites.net/