DynamicObject 類別

定義

提供一個基底類別,用於在執行時指定動態行為。 此類別必須繼承自:你無法直接實例化它。

public ref class DynamicObject : System::Dynamic::IDynamicMetaObjectProvider
public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating a call site may require dynamic code generation.")]
public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider
[System.Serializable]
public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider
type DynamicObject = class
    interface IDynamicMetaObjectProvider
[<System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating a call site may require dynamic code generation.")>]
type DynamicObject = class
    interface IDynamicMetaObjectProvider
[<System.Serializable>]
type DynamicObject = class
    interface IDynamicMetaObjectProvider
Public Class DynamicObject
Implements IDynamicMetaObjectProvider
繼承
DynamicObject
衍生
屬性
實作

範例

假設你想提供替代語法來存取字典中的值,這樣你就不用寫 sampleDictionary["Text"] = "Sample text"(Visual Basic 中的 sampleDictionary("Text") = "Sample text"),而是寫成 sampleDictionary.Text = "Sample text"。 此外,你希望這個語法不區分大小寫,所以 sampleDictionary.Text 相當於 sampleDictionary.text

以下程式碼範例展示了 DynamicDictionary 由該 DynamicObject 類別衍生而來的類別。 DynamicDictionary 類別包含一個 Dictionary<string, object> 型別的物件(Visual Basic 中的 Dictionary(Of String, Object))用來儲存鍵值對,並覆蓋 TrySetMemberTryGetMember 方法以支援新的語法。 它也提供一個 Count 性質,顯示字典包含多少動態性質。

// The class derived from DynamicObject.
public class DynamicDictionary : DynamicObject
{
    // The inner dictionary.
    Dictionary<string, object> dictionary
        = new Dictionary<string, object>();

    // This property returns the number of elements
    // in the inner dictionary.
    public int Count
    {
        get
        {
            return dictionary.Count;
        }
    }

    // If you try to get a value of a property
    // not defined in the class, this method is called.
    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        // Converting the property name to lowercase
        // so that property names become case-insensitive.
        string name = binder.Name.ToLower();

        // If the property name is found in a dictionary,
        // set the result parameter to the property value and return true.
        // Otherwise, return false.
        return dictionary.TryGetValue(name, out result);
    }

    // If you try to set a value of a property that is
    // not defined in the class, this method is called.
    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        // Converting the property name to lowercase
        // so that property names become case-insensitive.
        dictionary[binder.Name.ToLower()] = value;

        // You can always add a value to a dictionary,
        // so this method always returns true.
        return true;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Creating a dynamic dictionary.
        dynamic person = new DynamicDictionary();

        // Adding new dynamic properties.
        // The TrySetMember method is called.
        person.FirstName = "Ellen";
        person.LastName = "Adams";

        // Getting values of the dynamic properties.
        // The TryGetMember method is called.
        // Note that property names are case-insensitive.
        Console.WriteLine(person.firstname + " " + person.lastname);

        // Getting the value of the Count property.
        // The TryGetMember is not called,
        // because the property is defined in the class.
        Console.WriteLine(
            "Number of dynamic properties:" + person.Count);

        // The following statement throws an exception at run time.
        // There is no "address" property,
        // so the TryGetMember method returns false and this causes a
        // RuntimeBinderException.
        // Console.WriteLine(person.address);
    }
}

// This example has the following output:
// Ellen Adams
// Number of dynamic properties: 2
' The class derived from DynamicObject.
Public Class DynamicDictionary
    Inherits DynamicObject

    ' The inner dictionary.
    Dim dictionary As New Dictionary(Of String, Object)

    ' This property returns the number of elements
    ' in the inner dictionary.
    ReadOnly Property Count As Integer
        Get
            Return dictionary.Count
        End Get
    End Property


    ' If you try to get a value of a property that is
    ' not defined in the class, this method is called.

    Public Overrides Function TryGetMember(
        ByVal binder As System.Dynamic.GetMemberBinder,
        ByRef result As Object) As Boolean

        ' Converting the property name to lowercase
        ' so that property names become case-insensitive.
        Dim name As String = binder.Name.ToLower()

        ' If the property name is found in a dictionary,
        ' set the result parameter to the property value and return true.
        ' Otherwise, return false.
        Return dictionary.TryGetValue(name, result)
    End Function

    Public Overrides Function TrySetMember(
        ByVal binder As System.Dynamic.SetMemberBinder,
        ByVal value As Object) As Boolean

        ' Converting the property name to lowercase
        ' so that property names become case-insensitive.
        dictionary(binder.Name.ToLower()) = value

        ' You can always add a value to a dictionary,
        ' so this method always returns true.
        Return True
    End Function
End Class

Sub Main()
    ' Creating a dynamic dictionary.
    Dim person As Object = New DynamicDictionary()

    ' Adding new dynamic properties.
    ' The TrySetMember method is called.
    person.FirstName = "Ellen"
    person.LastName = "Adams"

    ' Getting values of the dynamic properties.
    ' The TryGetMember method is called.
    ' Note that property names are now case-insensitive,
    ' although they are case-sensitive in C#.
    Console.WriteLine(person.firstname & " " & person.lastname)

    ' Getting the value of the Count property.
    ' The TryGetMember is not called, 
    ' because the property is defined in the class.
    Console.WriteLine("Number of dynamic properties:" & person.Count)

    ' The following statement throws an exception at run time.
    ' There is no "address" property,
    ' so the TryGetMember method returns false and this causes
    ' a MissingMemberException.
    ' Console.WriteLine(person.address)
End Sub
' This examples has the following output:
' Ellen Adams
' Number of dynamic properties: 2

更多範例請參見 C# 常見問題部落格上的 「用 Dynamic Object 建立包裝器 」。

備註

這個 DynamicObject 類別讓你能定義可以對動態物件執行哪些操作,以及如何執行這些操作。 例如,你可以定義當你嘗試取得或設定物件屬性、呼叫方法,或執行標準數學運算如加法和乘法時會發生什麼。

如果你想為函式庫建立更方便的協定,這堂課會很有用。 例如,如果你函式庫的使用者必須使用像 Scriptobj.SetProperty("Count", 1)這樣的語法,你可以提供使用更簡單的語法功能,例如 scriptobj.Count = 1

你無法直接建立該 DynamicObject 類別的實例。 要實作動態行為,你可能想從類別繼承 DynamicObject 並覆蓋必要的方法。 例如,如果你只需要設定和取得屬性的操作,你可以只 TrySetMember 覆蓋 and TryGetMember 方法。

在 C# 中,要啟用由該 DynamicObject 類別衍生的類別實例的動態行為,必須使用 dynamic 關鍵字。 如需詳細資訊,請參閱 使用動態類型

在 Visual Basic 中,晚期系結支持動態作業。 如需詳細資訊,請參閱 早期和晚期系結 (Visual Basic)

以下程式碼範例示範如何建立由該 DynamicObject 類別衍生的類別實例。

public class SampleDynamicObject : DynamicObject {}
//...
dynamic sampleObject = new SampleDynamicObject ();
Public Class SampleDynamicObject
    Inherits DynamicObject
'...
Dim sampleObject As Object = New SampleDynamicObject()

你也可以將自己的成員加入由該 DynamicObject 類別衍生的類別中。 如果你的類別定義屬性並覆蓋該 TrySetMember 方法,動態語言執行時(DLR)會先使用語言綁定器尋找類別中屬性的靜態定義。 若不存在此性質,DLR 會呼叫該 TrySetMember 方法。

DynamicObject 類別實作了 DLR 介面 IDynamicMetaObjectProvider,讓你能在支援 DLR 互通模型的語言間共享該 DynamicObject 類別的實例。 例如,您可以在 C# 中建立 類別的 DynamicObject 實例,然後將它傳遞至 IronPython 函式。 欲了解更多資訊,請參閱 動態語言執行時概述

備註

如果你有一個簡單的情境,需要一個只能在執行時新增和移除成員,但不需要定義特定操作且沒有靜態成員的物件,請使用 該 ExpandoObject 類別。

如果你有更進階的情境,需要定義動態物件如何參與互通性協定,或是需要管理 DLR 快速動態派遣快取,請自行實作介面 IDynamicMetaObjectProvider

建構函式

名稱 Description
DynamicObject()

使衍生型態能夠初始化該 DynamicObject 型別的新實例。

方法

名稱 Description
Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
GetDynamicMemberNames()

回傳所有動態成員名稱的枚舉。

GetHashCode()

做為預設哈希函式。

(繼承來源 Object)
GetMetaObject(Expression)

提供 DynamicMetaObject 一個可以派遣到動態虛擬方法的 物件可以封裝在另一個 DynamicMetaObject 物件中,為個別動作提供自訂行為。 此方法支援語言實作者的動態語言執行環境基礎設施,並非直接從您的程式碼中使用。

GetType()

取得目前實例的 Type

(繼承來源 Object)
MemberwiseClone()

建立目前 Object的淺層複本。

(繼承來源 Object)
ToString()

傳回表示目前 物件的字串。

(繼承來源 Object)
TryBinaryOperation(BinaryOperationBinder, Object, Object)

提供二進位運算的實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定加法與乘法等運算的動態行為。

TryConvert(ConvertBinder, Object)

提供型別轉換操作的實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定將物件從一種型態轉換到另一種型態的動態行為。

TryCreateInstance(CreateInstanceBinder, Object[], Object)

提供初始化動態物件新實例的操作實作。 此方法不適用於 C# 或 Visual Basic。

TryDeleteIndex(DeleteIndexBinder, Object[])

提供以索引刪除物件的操作實作。 此方法不適用於 C# 或 Visual Basic。

TryDeleteMember(DeleteMemberBinder)

提供刪除物件成員操作的實作。 此方法不適用於 C# 或 Visual Basic。

TryGetIndex(GetIndexBinder, Object[], Object)

提供透過索引取得值的操作實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定索引操作的動態行為。

TryGetMember(GetMemberBinder, Object)

提供取得成員值的操作實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定動態行為,例如取得屬性值。

TryInvoke(InvokeBinder, Object[], Object)

提供呼叫物件操作的實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定像是調用物件或代理等操作的動態行為。

TryInvokeMember(InvokeMemberBinder, Object[], Object)

提供呼叫成員操作的實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定操作的動態行為,例如呼叫方法。

TrySetIndex(SetIndexBinder, Object[], Object)

提供以索引設定值的操作實作。 從該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定對透過指定索引存取物件的操作進行動態行為。

TrySetMember(SetMemberBinder, Object)

提供設定成員值的操作實作。 由該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定動態行為,例如設定屬性值。

TryUnaryOperation(UnaryOperationBinder, Object)

提供一元運算的實作。 由該 DynamicObject 類別衍生的類別可以覆寫此方法,以指定如否定、遞增或遞減等操作的動態行為。

適用於