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 關鍵詞。 如需詳細資訊,請參閱使用動態類型

在 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 實例。 如果您在編譯時期不知道實例可能擁有的成員,這會很有用。

下列程式代碼範例示範如何將 類別的 ExpandoObject 實例轉換成 介面, IDictionary<TKey,TValue> 並列舉實例的成員。

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

在沒有刪除成員語法的語言中,您可以藉由隱含地將 的實例ExpandoObjectIDictionary<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