c# - 如何将 Expression 转换为 CSharpCompilation 或 CSharpSyntaxTree?

标签 c# .net roslyn

如何转换:

System.Linq.Expression.Expression

进入:

Microsoft.CodeAnalysis.CSharp.CSharpCompilation

或进入:

Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree

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

  • 我可以将 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
    }
    

更新:

方法 Expression -> string -> Roslyn Not Acceptable 。转化应该是直接的。

更新 2: 可能的用法:

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

一个。更快的启动

编译时错误,而不是运行时错误。

可能更快的运行时间。

吃 F# 饼,让 C# 活得更久。

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

  1. 将这些转换为 C# 代码的表达式库(例如用于调试)。

一个。更多代码输出选项(命名空间、空格、制表符)。 b.更少的手动生成代码更正确。 C。支持不同的输出语言而不是 C#。

最佳答案

参见here syntax transformation

Because the syntax trees are immutable, the Syntax API provides no direct mechanism for modifying an existing syntax tree after construction. However, the Syntax API does provide methods for producing new trees based on specified changes to existing ones. Each concrete class that derives from SyntaxNode defines With* methods which you can use to specify changes to its child properties.

Additionally, the ReplaceNode extension method can be used to replace a descendent node in a subtree. Without this method updating a node would also require manually updating its parent to point to the newly created child and repeating this process up the entire tree

  • a process known as re-spining the tree.

示例 - 使用 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/

关于c# - 如何将 Expression 转换为 CSharpCompilation 或 CSharpSyntaxTree?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48790497/

相关文章:

c# - windows phone 7开发的MVVM框架推荐

.net - 使用 Visual Studio 部署 Umbraco 站点

c# - 无法创建新的 "Diagnostics with code fix"项目! (罗斯林+VS2013)

c# - 从循环条件获取 Microsoft Roslyn 的迭代次数

C# 与 MySQL 连接器 - 访问被拒绝

c# - OracleConnection 抛出空异常

.net - 多个项目需要使用1个SNK文件

c# - 如何获取具有指定属性的所有字段的列表?

c# - 如何在使用 shell 和选项卡的 .NET MAUI 应用程序中实现注销?

c# - 查找正则表达式以匹配特定单词