官方文档
ExpandoObject 类 (System.Dynamic) | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/api/system.dynamic.expandoobject?view=net-8.0
System.Dynamic.ExpandoObject 类 - .NET | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/fundamentals/runtime-libraries/system-dynamic-expandoobject
介绍
如果看不懂,没关系,可以看下面的示例代码
通过 ExpandoObject 该类,你可以在运行时添加和删除其实例的成员,以及设置和获取这些成员的值。 此类支持动态绑定,因此可以使用标准语法,例如 sampleObject.sampleMember
,而不是更复杂的 sampleObject.GetAttribute("sampleMember")
语法。
该 ExpandoObject
类实现标准动态语言运行时 (DLR) 接口 IDynamicMetaObjectProvider,使你可以在支持 DLR 互操作性模型的语言之间共享类的 ExpandoObject
实例。 例如,可以在 C# 中创建类的 ExpandoObject
实例,然后将其传递给 IronPython 函数。 有关详细信息,请参阅 动态语言运行时概述 和 ExpandoObject 简介。
该 ExpandoObject
类是动态对象概念的实现,可实现获取、设置和调用成员。 如果要定义具有其自己的动态调度语义的类型,请使用该 DynamicObject 类。 如果要定义动态对象如何参与互操作性协议并管理 DLR 快速动态调度缓存,请创建自己的接口实现 IDynamicMetaObjectProvider 。
示例代码
在 C# 中,若要为类的
ExpandoObject
实例启用后期绑定,必须使用dynamic
关键字 (keyword)。 有关更多信息,请参见使用类型 dynamic。
创建实例
dynamic sampleObject = new ExpandoObject();
添加新成员
可以将属性、方法和事件添加到类的 ExpandoObject
实例。
下面的代码示例演示如何向类的 ExpandoObject
实例添加新属性。
sampleObject.test = "Dynamic Property";
Console.WriteLine(sampleObject.test);
Console.WriteLine(sampleObject.test.GetType());
作为参数传递
class Program
{
static void Main(string[] args)
{
dynamic employee, manager;
employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
WritePerson(manager);
WritePerson(employee);
}
private static void WritePerson(dynamic person)
{
Console.WriteLine("{0} is {1} years old.",
person.Name, person.Age);
}
}
【*重点】枚举和删除成员
ExpandoObject
类实现 IDictionary<String, Object>
接口。 这样就可以在运行时枚举添加到类实例 ExpandoObject
的成员。 如果在编译时不知道实例可能具有的成员,这可能很有用。
下面的代码示例演示如何将类IDictionary<TKey,TValue>的ExpandoObject
实例强制转换为接口并枚举实例的成员。
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<String, Object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
在不使用语法删除成员(如 C# 和 Visual Basic)的语言中,可以通过隐式将接口的ExpandoObject
IDictionary<String, Object>
实例强制转换为接口,然后将成员删除为键/值对来删除成员。 这在下面的示例中显示。
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");
【*重点】既然是这样,我们可以这样操作,来读取值
假设【users】的类型是IEnumerable<dynamic>,他的本质是一个List<dynamic>集合(虽然这样说不严谨,你可以先这样理解);他里面的每项元素的类型是System.Dynamic.ExpandoObject;
我们可以这样读取值
foreach (IDictionary<string, object> user in users)
{
foreach (var item in user)
{
Console.WriteLine($"Key:{item.Key}--Value:{item.Value}");
}
}
解释:
假设【users】的类型是IEnumerable<dynamic>,他的本质是一个List<dynamic>集合(虽然这样说不严谨,你可以先这样理解)
我为什么这样说呢?
下面代码是list源码,我们可以看到它继承了 IEnumerable<T>和IEnumerable;
那么IEnumerable<dynamic>就等于 IEnumerable<T>;
所以我说:IEnumerable<dynamic>类型,他的本质是一个List<dynamic>集合; 这个理解也算合理
public class List<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList
{
public List();
public List(int capacity);
}