首页 .NET C# 表达式树 Expression.Dynamic 使用教程

C# 表达式树 Expression.Dynamic 使用教程

Expression.Dynamic 是 C# 表达式树 (System.Linq.Expressions) 中的一个方法,主要用于 动态绑定,它可以在运行时执行不同的操作,而无需在编译时确定具体的类型或方法。常见的应用场景包括 动态语言互操作(如与 dynamic 变量交互)、反射调用 以及 动态计算表达式。

1. 什么是 Expression.Dynamic?

在 C# 中,Expression.Dynamic 允许我们创建一个 动态操作表达式,这个表达式在执行时会委托给指定的 CallSiteBinder 进行绑定。例如,在使用 dynamic 类型的情况下,C# 需要在运行时决定具体的操作,而 Expression.Dynamic 可以帮助构造这样的调用。

2. 基本使用方式

2.1 代码示例:动态调用方法

以下示例展示了如何使用 Expression.Dynamic 调用一个动态方法:

using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;

class Program
{
    static void Main()
    {
        // 定义一个 dynamic 变量
        dynamic target = "Hello, Expression.Dynamic!";

        // 创建一个 CallSiteBinder,表示对成员 "ToUpper" 进行调用
        CallSiteBinder binder = Binder.InvokeMember(
            CSharpBinderFlags.None, // 无特殊标志
            "ToUpper",              // 需要调用的方法名
            null,                   // 泛型参数(如果有的话)
            typeof(Program),         // 调用的上下文类型
            new CSharpArgumentInfo[] {
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
            }
        );

        // 创建动态表达式
        Expression dynamicExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(target));

        // 编译并执行
        var lambda = Expression.Lambda<Func<object>>(dynamicExpression).Compile();
        object result = lambda();

        Console.WriteLine(result); // 输出: "HELLO, EXPRESSION.DYNAMIC!"
    }
}

代码说明

Binder.InvokeMember 创建一个绑定器(CallSiteBinder),指定了方法名 "ToUpper",用于动态调用该方法。

Expression.Dynamic 创建一个动态调用表达式,参数包括:

绑定器 binder 结果类型 typeof(object) 目标对象 Expression.Constant(target)

Expression.Lambda<Func<object>> 生成一个 Lambda 表达式,随后编译并执行。

3. Expression.Dynamic 的应用场景

3.1 结合 dynamic 实现运行时方法调用

在需要和 dynamic 变量交互的情况下,可以使用 Expression.Dynamic 直接在表达式树中操作 dynamic 类型,而不需要手动使用 dynamic 关键字。

3.2 处理动态对象(如 ExpandoObject)

在与 ExpandoObject 交互时,可以使用 Expression.Dynamic 让表达式树正确解析动态属性或方法。例如:

using System;
using System.Dynamic;
using System.Linq.Expressions;
using Microsoft.CSharp.RuntimeBinder;

class Program
{
    static void Main()
    {
        dynamic expando = new ExpandoObject();
        expando.Name = "ChatGPT";

        // 创建动态调用的 Binder
        CallSiteBinder binder = Binder.GetMember(
            CSharpBinderFlags.None,
            "Name",
            typeof(Program),
            new CSharpArgumentInfo[] {
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
            }
        );

        // 创建表达式树
        Expression dynamicExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(expando));
        var lambda = Expression.Lambda<Func<object>>(dynamicExpression).Compile();

        Console.WriteLine(lambda()); // 输出: "ChatGPT"
    }
}

这里 Binder.GetMember 允许我们在运行时获取 ExpandoObject 的 "Name" 属性。

4. 注意事项

Expression.Dynamic 需要 Microsoft.CSharp.RuntimeBinder 提供 Binder,否则无法正确解析 C# 语言的动态绑定。由于 Expression.Dynamic 在运行时绑定方法或属性,性能比静态调用略低,因此应慎重使用,避免影响性能。Expression.Dynamic 仅适用于 动态类型交互,如果是静态类型,可以直接使用 Expression.Call 等方法。

Expression.Dynamic 提供了 在表达式树中使用动态绑定的能力,适用于处理 dynamic 类型、ExpandoObject、运行时计算表达式等场景。它允许开发者在 不确定目标类型 的情况下执行方法调用或属性访问,从而增强代码的灵活性。

站心网

Expression.Dynamic 是 C# 表达式树 (System.Linq.Expressions) 中的一个方法,主要用于 动态绑定,它可以..

为您推荐

.NET(C#)使用 iText7 高效处理PDF文件的全面指南​

在现代软件开发中,PDF 文件处理是一个常见且重要的需求。无论是生成报告、填充表单、添加水印,还是进行数字签名,选择一个功能强大的 PDF 库至关重要。iText7 作为一款开源且功能丰富的 PDF 操作库,广泛应用于 C#..

.NET C# 过滤从富文本编辑器html里的Javascript脚本

富文本编辑器在允许用户输入丰富内容的同时,也带来了跨站脚本攻击(XSS)的风险。过滤提交的 HTML 中的 <script> 脚本是防止跨站脚本攻击(XSS)的关键步骤。在 .NET C# 服务端过滤 <script> 脚本主要有以下几种方..

.NET C# RESTful API交互Refit库使用教程

Refit 是一个 .NET C# 库,它简化了与 RESTful API 的交互。Refit 受到 Square 的 Retrofit 库的启发,它将 REST API 转换为实时接口,允许你以声明方式定义 REST API 调用。Refit 的特点1. 声明式 API 定义:Refit ..

.NET C# System.Text.Json进阶使用技巧

System.Text.Json 是 .NET 中用于处理 JSON 数据的强大库。除了基本用法外,它还提供了许多进阶技巧,可以帮助你更高效、更灵活地处理 JSON 数据。以下是一些 System.Text.Json 的进阶使用技巧:1. 自定义序列化和反..

.NET C# 单元测试 mock File.Exists的返回值

在 .NET 单元测试中,使用 Moq 来模拟 File.Exists 方法的返回值,可以这样做:1. 使用 Mock<FileSystem>(推荐).NET 提供了 System.IO.Abstractions 库,你可以使用 Mock<IFileSystem> 来替代 File,这样更符合依..

2025年.NET 10 和 C# 13 新特性示例

.NET 10预计将于2025年11月正式发布,带来一系列性能优化、开发者效率提升和跨平台能力增强。尽管官方功能集仍在开发中,早期预览版与社区讨论已揭示了多项值得期待的改进。这些增强将基于.NET 9的基础,引入新语言..

.NET10 C#13最新语法糖用法示例

.NET 10 与 C# 13 带来了更高效的语法和更灵活的类型支持,包括 params 集合扩展、新的 \e 转义序列、方法组的自然类型推断优化,以及 ref struct 允许实现接口等特性,进一步提升了开发体验和代码可读性。C# 13 引..

.NET C# Predicate泛型委托使用方法

Predicate泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。 Predicate<T> 通常用于集合的筛选或搜索操作,比如在 List<T> 的 Fi..

发表回复

返回顶部

微信分享

微信分享二维码

扫描二维码分享到微信或朋友圈

链接已复制