System.Dynamic.ExpandoObject 类
本文提供了此 API 参考文档的补充说明。
通过 ExpandoObject 该类,你可以在运行时添加和删除其实例的成员,以及设置和获取这些成员的值。 此类支持动态绑定,因此可以使用标准语法,例如 sampleObject.sampleMember
,而不是更复杂的 sampleObject.GetAttribute("sampleMember")
语法。
该 ExpandoObject
类实现标准动态语言运行时 (DLR) 接口 IDynamicMetaObjectProvider,使你可以在支持 DLR 互操作性模型的语言之间共享类的 ExpandoObject
实例。 例如,可以在 C# 中创建类的 ExpandoObject
实例,然后将其传递给 IronPython 函数。 有关详细信息,请参阅 动态语言运行时概述 和 ExpandoObject 简介。
该 ExpandoObject
类是动态对象概念的实现,可实现获取、设置和调用成员。 如果要定义具有其自己的动态调度语义的类型,请使用该 DynamicObject 类。 如果要定义动态对象如何参与互操作性协议并管理 DLR 快速动态调度缓存,请创建自己的接口实现 IDynamicMetaObjectProvider 。
创建实例
在 C# 中,若要为类的ExpandoObject
实例启用后期绑定,必须使用dynamic
关键字 (keyword)。 有关更多信息,请参见使用类型 dynamic。
在 Visual Basic 中,后期绑定支持动态操作。 有关详细信息,请参阅早期绑定和后期绑定(Visual Basic)。
下面的代码示例演示如何创建类的 ExpandoObject
实例。
dynamic sampleObject = new ExpandoObject();
Dim sampleObject As Object = New ExpandoObject()
添加新成员
可以将属性、方法和事件添加到类的 ExpandoObject
实例。
下面的代码示例演示如何向类的 ExpandoObject
实例添加新属性。
sampleObject.test = "Dynamic Property";
Console.WriteLine(sampleObject.test);
Console.WriteLine(sampleObject.test.GetType());
// This code example produces the following output:
// Dynamic Property
// System.String
sampleObject.Test = "Dynamic Property"
Console.WriteLine(sampleObject.test)
Console.WriteLine(sampleObject.test.GetType())
' This code example produces the following output:
' Dynamic Property
' System.String
这些方法表示存储为委托的 lambda 表达式,这些表达式在需要时可以调用这些表达式。 下面的代码示例演示如何添加递增动态属性值的方法。
sampleObject.number = 10;
sampleObject.Increment = (Action)(() => { sampleObject.number++; });
// Before calling the Increment method.
Console.WriteLine(sampleObject.number);
sampleObject.Increment();
// After calling the Increment method.
Console.WriteLine(sampleObject.number);
// This code example produces the following output:
// 10
// 11
sampleObject.Number = 10
sampleObject.Increment = Function() sampleObject.Number + 1
' Before calling the Increment method.
Console.WriteLine(sampleObject.number)
sampleObject.Increment.Invoke()
' After calling the Increment method.
Console.WriteLine(sampleObject.number)
' This code example produces the following output:
' 10
' 11
下面的代码示例演示如何将事件添加到类的 ExpandoObject
实例。
class Program
{
static void Main(string[] args)
{
dynamic sampleObject = new ExpandoObject();
// Create a new event and initialize it with null.
sampleObject.sampleEvent = null;
// Add an event handler.
sampleObject.sampleEvent += new EventHandler(SampleHandler);
// Raise an event for testing purposes.
sampleObject.sampleEvent(sampleObject, new EventArgs());
}
// Event handler.
static void SampleHandler(object sender, EventArgs e)
{
Console.WriteLine("SampleHandler for {0} event", sender);
}
}
// This code example produces the following output:
// SampleHandler for System.Dynamic.ExpandoObject event.
Module Module1
Sub Main()
Dim sampleObject As Object = New ExpandoObject()
' Create a new event and initialize it with null.
sampleObject.sampleEvent = Nothing
' Add an event handler.
Dim handler As EventHandler = AddressOf SampleHandler
sampleObject.sampleEvent =
[Delegate].Combine(sampleObject.sampleEvent, handler)
' Raise an event for testing purposes.
sampleObject.sampleEvent.Invoke(sampleObject, New EventArgs())
End Sub
' Event handler.
Sub SampleHandler(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("SampleHandler for {0} event", sender)
End Sub
' This code example produces the following output:
' SampleHandler for System.Dynamic.ExpandoObject event.
End Module
作为参数传递
可以将类的 ExpandoObject
实例作为参数传递。 请注意,这些实例被视为 C# 中的动态对象和 Visual Basic 中的后期绑定对象。 这意味着你没有对象成员的 IntelliSense,并且调用不存在的成员时不会收到编译器错误。 如果调用不存在的成员,将发生异常。
下面的代码示例演示如何创建和使用方法打印属性的名称和值。
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);
// The following statement causes an exception
// if you pass the employee object.
// Console.WriteLine("Manages {0} people", person.TeamSize);
}
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.
Sub Main()
Dim employee, manager As Object
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)
End Sub
Private Sub WritePerson(ByVal person As Object)
Console.WriteLine("{0} is {1} years old.",
person.Name, person.Age)
' The following statement causes an exception
' if you pass the employee object.
' Console.WriteLine("Manages {0} people", person.TeamSize)
End Sub
枚举和删除成员
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);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33
Dim employee As Object = New ExpandoObject()
employee.Name = "John Smith"
employee.Age = 33
For Each member In CType(employee, IDictionary(Of String, Object))
Console.WriteLine(member.Key & ": " & member.Value)
Next
' This code example produces the following output:
' Name: John Smith
' Age: 33
在不使用语法删除成员(如 C# 和 Visual Basic)的语言中,可以通过隐式将接口的ExpandoObject
IDictionary<String, Object>
实例强制转换为接口,然后将成员删除为键/值对来删除成员。 这在下面的示例中显示。
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");
Dim employee As Object = New ExpandoObject()
employee.Name = "John Smith"
CType(employee, IDictionary(Of String, Object)).Remove("Name")
接收属性更改通知
该 ExpandoObject
类实现接口, INotifyPropertyChanged 并在添加、删除或修改成员时引发 PropertyChanged 事件。 这使类能够 ExpandoObject
与 Windows Presentation Foundation (WPF) 数据绑定和其他环境集成,这些环境需要通知对象内容中的更改。
下面的代码示例演示如何为 PropertyChanged
事件创建事件处理程序。
// Add "using System.ComponentModel;" line
// to the beginning of the file.
class Program
{
static void Test()
{
dynamic employee = new ExpandoObject();
((INotifyPropertyChanged)employee).PropertyChanged +=
new PropertyChangedEventHandler(HandlePropertyChanges);
employee.Name = "John Smith";
}
private static void HandlePropertyChanges(
object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("{0} has changed.", e.PropertyName);
}
}
' Add "Imports System.ComponentModel" line
' to the beginning of the file.
Sub Main()
Dim employee As Object = New ExpandoObject
AddHandler CType(
employee, INotifyPropertyChanged).PropertyChanged,
AddressOf HandlePropertyChanges
employee.Name = "John Smith"
End Sub
Private Sub HandlePropertyChanges(
ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
Console.WriteLine("{0} has changed.", e.PropertyName)
End Sub