DynamicObject 类

定义

提供用于在运行时指定动态行为的基类。 必须继承此类;不能直接对其进行实例化。

public ref class DynamicObject : System::Dynamic::IDynamicMetaObjectProvider
public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider
[System.Serializable]
public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider
type DynamicObject = class
    interface IDynamicMetaObjectProvider
[<System.Serializable>]
type DynamicObject = class
    interface IDynamicMetaObjectProvider
Public Class DynamicObject
Implements IDynamicMetaObjectProvider
继承
DynamicObject
派生
属性
实现

示例

假设你想要提供用于访问字典中的值的替代语法,这样就可以编写 sampleDictionary.Text = "Sample text"sampleDictionary("Text") = "Sample text"而不是在 Visual Basic) 中编写 sampleDictionary["Text"] = "Sample text" (。 此外,你希望此语法不区分大小写,以便等效 sampleDictionary.TextsampleDictionary.text

下面的代码示例演示 DynamicDictionary 派生自 类的 DynamicObject 类。 类DynamicDictionary包含 Visual Basic 中 (Dictionary(Of String, Object) 类型的对象Dictionary<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# 常见问题解答博客上的 使用 DynamicObject 创建包装器

注解

使用 DynamicObject 类可以定义可以对动态对象执行哪些操作以及如何执行这些操作。 例如,可以定义尝试获取或设置对象属性、调用方法或执行标准数学运算(如加法和乘法)时会发生什么情况。

如果要为库创建更方便的协议,此类可能很有用。 例如,如果库的用户必须使用 等 Scriptobj.SetProperty("Count", 1)语法,则可以提供使用更简单的语法的功能,例如 scriptobj.Count = 1

不能直接创建 类的 DynamicObject 实例。 若要实现动态行为,可能需要从 DynamicObject 类继承并重写必要的方法。 例如,如果只需要设置和获取属性的操作,则可以仅 TrySetMember 重写 和 TryGetMember 方法。

在 C# 中,若要为派生自 DynamicObject 类的类实例启用动态行为,必须使用 dynamic 关键字 (keyword) 。 有关更多信息,请参见使用类型 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

构造函数

DynamicObject()

使派生的类型可以初始化 DynamicObject 类型的新实例。

方法

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 类派生的类可以重写此方法,以便为诸如求反、递增、递减这样的运算指定动态行为。

适用于