0

0

C#的ExpandoObject如何动态添加属性?

星降

星降

发布时间:2025-08-14 11:06:02

|

942人浏览过

|

来源于php中文网

原创

expandoobject 允许在运行时动态添加属性,适用于处理未知结构的数据;1. 可像字典一样添加属性:直接赋值即可;2. 删除属性:通过 idictionary 接口的 remove 方法实现;3. 检查属性是否存在:使用 containskey 方法判断;4. 遍历属性:可 foreach 遍历其键值对;它在动态 json 反序列化、简化数据转换、动态配置、测试与原型设计中特别有用;相比强类型对象,优点是灵活性高、易用且无需预定义类,缺点是缺乏类型安全、性能较低、可维护性差;为避免陷阱,应谨慎使用,优先在数据结构不确定时采用,配合单元测试保障正确性,必要时继承 dynamicobject 重写 trygetmember 和 trysetmember 实现自定义逻辑,或实现 idynamicmetaobjectprovider 进行更底层控制。

C#的ExpandoObject如何动态添加属性?

直接来说,C# 的 ExpandoObject 允许你在运行时动态地添加属性,这提供了一种非常灵活的方式来处理未知结构的数据,或者构建动态的模型。

解决方案

ExpandoObject 实际上是一个实现了

IDictionary
接口的类。这意味着你可以像操作字典一样操作它的属性。

添加属性:

最简单的方法就是像操作字典一样,直接赋值:

dynamic expando = new ExpandoObject();
expando.Name = "张三";
expando.Age = 30;

Console.WriteLine(expando.Name); // 输出: 张三
Console.WriteLine(expando.Age);  // 输出: 30

删除属性:

由于 ExpandoObject 实现了

IDictionary
接口,你可以使用
Remove
方法删除属性:

IDictionary expandoDict = expando as IDictionary;
expandoDict.Remove("Age");

// 尝试访问 Age 会抛出异常,或者返回 null,取决于你如何处理动态对象的访问
try
{
    Console.WriteLine(expando.Age);
}
catch (RuntimeBinderException ex)
{
    Console.WriteLine("属性不存在"); // 输出: 属性不存在
}

检查属性是否存在:

你可以使用

ContainsKey
方法检查属性是否存在:

if (expandoDict.ContainsKey("Name"))
{
    Console.WriteLine("Name 属性存在"); // 输出: Name 属性存在
}

循环遍历属性:

因为 ExpandoObject 实现了

IDictionary
接口,你可以像遍历字典一样遍历它的属性:

foreach (var kvp in expandoDict)
{
    Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}

ExpandoObject 在哪些场景下特别有用?

SUN2008 企业网站管理系统2.0 beta
SUN2008 企业网站管理系统2.0 beta

1、数据调用该功能使界面与程序分离实施变得更加容易,美工无需任何编程基础即可完成数据调用操作。2、交互设计该功能可以方便的为栏目提供个性化性息功能及交互功能,为产品栏目添加产品颜色尺寸等属性或简单的留言和订单功能无需另外开发模块。3、静态生成触发式静态生成。4、友好URL设置网页路径变得更加友好5、多语言设计1)UTF8国际编码; 2)理论上可以承担一个任意多语言的网站版本。6、缓存机制减轻服务器

下载

ExpandoObject 在处理以下场景时非常有用:

  • 动态 JSON 反序列化: 当你需要处理结构未知的 JSON 数据时,可以将 JSON 反序列化为 ExpandoObject,然后动态访问其中的属性,而无需预先定义类结构。这在处理来自外部 API 的数据时尤其有用。
using System.Text.Json;

string jsonString = "{ \"name\": \"李四\", \"city\": \"北京\" }";
dynamic obj = JsonSerializer.Deserialize(jsonString);
Console.WriteLine(obj.name); // 输出: 李四
Console.WriteLine(obj.city); // 输出: 北京
  • 简化数据转换: 如果你需要在不同的数据结构之间进行转换,而又不想创建大量的中间类,可以使用 ExpandoObject 作为桥梁。 可以将数据源的属性复制到 ExpandoObject,然后将其传递给需要不同数据结构的组件。

  • 动态配置: 可以利用 ExpandoObject 构建动态配置系统。 将配置信息存储在 ExpandoObject 中,允许在运行时修改配置,而无需重新编译代码。

  • 测试和原型设计: 在测试或原型设计阶段,当数据结构尚未完全确定时,可以使用 ExpandoObject 快速创建动态对象,以便进行实验和验证。

ExpandoObject 与强类型对象相比,有哪些优缺点?

优点:

  • 灵活性: 最大的优点就是灵活性。 你可以在运行时动态地添加、删除属性,无需预先定义类结构。
  • 易用性: 使用起来非常简单,就像操作字典一样。
  • 无需预定义类: 避免了创建大量 DTO (Data Transfer Object) 类的麻烦。

缺点:

  • 类型安全: 由于是动态类型,编译时无法进行类型检查,容易出现运行时错误。 例如,如果尝试访问一个不存在的属性,或者将一个字符串赋值给一个期望数字类型的属性,编译器无法发现这些错误,只能在运行时才能发现。
  • 性能: 动态类型的性能通常不如强类型。 每次访问属性都需要进行动态查找,这会带来一定的性能开销。
  • 可维护性: 由于缺乏类型信息,代码的可读性和可维护性可能会降低。 如果代码中大量使用 ExpandoObject,可能会使代码难以理解和调试。

如何避免 ExpandoObject 的常见陷阱?

  • 谨慎使用: 虽然 ExpandoObject 提供了很大的灵活性,但不要过度使用。 只有在真正需要动态类型的场景下才应该使用它。 如果数据结构是已知的,并且不会经常变化,那么应该优先使用强类型对象。

  • 单元测试: 由于 ExpandoObject 缺乏编译时类型检查,因此需要编写大量的单元测试来确保代码的正确性。 测试应该覆盖各种可能的场景,包括访问不存在的属性、赋值错误类型的值等等。

  • 使用动态语言特性: C# 的

    dynamic
    关键字允许你在编译时绕过类型检查,这使得你可以像在动态语言(如 Python 或 JavaScript)中一样操作对象。 但是,这也意味着你需要更加小心,因为编译器不会帮你发现类型错误。

  • 使用

    TryGetMember
    TrySetMember
    方法:
    如果你需要更精细地控制属性的访问和修改,可以继承
    DynamicObject
    类,并重写
    TryGetMember
    TrySetMember
    方法。 这允许你自定义属性的获取和设置逻辑,例如添加验证、类型转换等。

public class MyDynamicObject : DynamicObject
{
    private Dictionary _data = new Dictionary();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        string name = binder.Name.ToLower();
        if (_data.ContainsKey(name))
        {
            result = _data[name];
            return true;
        }
        else
        {
            result = null;
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        string name = binder.Name.ToLower();
        _data[name] = value;
        return true;
    }
}
  • 考虑使用
    IDynamicMetaObjectProvider
    接口:
    IDynamicMetaObjectProvider
    接口提供了更底层的动态对象模型支持。 你可以实现这个接口来创建完全自定义的动态对象,但这通常需要更深入的理解动态语言运行时。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

769

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

661

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

764

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

639

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1305

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.1万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号