跟着AI学习C# Day21

发布于:2025-06-21 ⋅ 阅读:(19) ⋅ 点赞:(0)

📅 Day 21:动态类型与动态语言运行时(Dynamic Types & DLR)

✅ 学习目标:

  • 理解什么是 dynamic 类型
  • 掌握 dynamicobject 的区别;
  • 理解 DLR(Dynamic Language Runtime) 的作用;
  • 学会使用 dynamic 简化反射、COM 互操作等场景;
  • 理解 ExpandoObjectDynamicObject 的用法;
  • 编写一个基于 dynamic 的 JSON 解析器或脚本执行器示例。

🧠 一、什么是 dynamic 类型?

在 C# 中,dynamic 是一种特殊的类型,它绕过了编译时的类型检查,将类型解析延迟到运行时进行。

示例:

dynamic x = 10;
x = "Hello";       // 合法
x = new Person();  // 合法

⚠️ 编译时不检查成员是否存在,运行时才会抛出异常。


🔁 二、dynamic vs object

特性 object dynamic
编译时类型检查
运行时解析
性能 更快 稍慢(需 DLR 解析)
适合场景 多态、泛型 反射简化、脚本交互

💡 三、DLR(Dynamic Language Runtime)

DLR(动态语言运行时) 是 .NET Framework 4 引入的一个子系统,用于支持动态语言(如 Python、Ruby)在 .NET 平台上的运行。它也支撑了 C# 中的 dynamic 功能。

DLR 的核心功能包括:

  • 运行时绑定(Runtime Binding)
  • 动态对象解析(如 COM 对象、Python 对象)
  • 缓存机制优化性能

🧩 四、常见使用场景

场景 1:简化反射调用

传统反射方式:

object obj = GetSomeObject();
MethodInfo method = obj.GetType().GetMethod("DoWork");
method.Invoke(obj, null);

使用 dynamic

dynamic obj = GetSomeObject();
obj.DoWork();  // 编译不报错,运行时自动解析

场景 2:COM 互操作(如 Excel 自动化)

Type excelType = Type.GetTypeFromProgID("Excel.Application");
dynamic excel = Activator.CreateInstance(excelType);
excel.Visible = true;
excel.Workbooks.Add();

场景 3:处理不确定结构的数据(如 JSON)

string json = "{\"Name\":\"张三\",\"Age\":25}";
dynamic data = JsonSerializer.Deserialize<JsonElement>(json);

Console.WriteLine(data.Name);
Console.WriteLine(data.Age);

🧱 五、System.Dynamic 命名空间

C# 提供了几个类来帮助你创建自定义的动态对象:

1. ExpandoObject

表示一个可以在运行时动态添加和删除成员的对象。

dynamic person = new ExpandoObject();
person.Name = "李四";
person.Age = 30;

person.SayHello = new Action(() => Console.WriteLine("你好!"));

person.SayHello();  // 输出:你好!

2. DynamicObject

你可以继承此类并重写其方法来自定义动态行为。

public class MyDynamic : DynamicObject
{
    private Dictionary<string, object> _properties = new();

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _properties[binder.Name] = value;
        return true;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _properties.TryGetValue(binder.Name, out result);
    }
}

// 使用
dynamic obj = new MyDynamic();
obj.Name = "王五";
Console.WriteLine(obj.Name);  // 输出:王五

🧪 六、动态表达式树(Expression Trees)

虽然 dynamic 很方便,但如果你需要高性能的动态行为,推荐使用 Expression<TDelegate> 构建动态委托。

ParameterExpression param = Expression.Parameter(typeof(int), "x");
Expression body = Expression.Multiply(param, param);
Func<int, int> square = Expression.Lambda<Func<int, int>>(body, param).Compile();

Console.WriteLine(square(5));  // 输出:25

💪 实战练习:构建一个简单的动态 JSON 解析器

功能要求:

  • 从 API 获取 JSON 数据;
  • 使用 dynamic 解析并输出字段;
  • 支持嵌套属性访问。
示例代码:
using System;
using System.Net.Http;
using System.Text.Json;

class Program
{
    static async Task Main()
    {
        using HttpClient client = new HttpClient();
        string json = await client.GetStringAsync("https://jsonplaceholder.typicode.com/users/1");

        dynamic user = JsonSerializer.Deserialize<JsonElement>(json);

        Console.WriteLine("用户ID:" + user.id);
        Console.WriteLine("用户名:" + user.username);
        Console.WriteLine("地址城市:" + user.address.city);
    }
}

⚠️ 七、注意事项与最佳实践

建议 说明
避免滥用 dynamic 它牺牲了编译时安全性和 IDE 智能提示
不要用于公共 API 应该优先使用接口或泛型
谨慎用于性能关键路径 DLR 有额外开销
在反射、JSON、COM 场景中合理使用 可显著提升开发效率

📝 小结

今天你学会了:

  • dynamic 类型的基本概念及其与 object 的区别;
  • 了解了 DLR(动态语言运行时) 的作用;
  • 掌握了如何使用 dynamic 简化反射、COM 互操作、JSON 解析等场景;
  • 学会使用 ExpandoObjectDynamicObject 创建自定义动态对象;
  • 编写了一个基于 dynamic 的 JSON 解析器示例;
  • 了解了 dynamic 的性能影响及适用场景。

dynamic 是 C# 中非常强大的工具,尤其适用于与外部系统交互、快速原型开发等场景。但在大型项目中应谨慎使用以确保可维护性。


🧩 下一步学习方向(Day 22)

明天我们将进入一个新的主题 —— LINQ(Language Integrated Query)基础与进阶,你将学会如何使用 LINQ 查询集合、数据库、XML,并掌握查询语法与方法语法的区别。


网站公告

今日签到

点亮在社区的每一天
去签到