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
派生
属性
实现

示例

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

下面的代码示例演示 DynamicDictionary 了派生自该类的 DynamicObject 类。 DynamicDictionary 类包含用于存储键值对的 Dictionary<string, object> 类型 (Dictionary(Of String, Object) Visual Basic) 的对象,并重写 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 关键字。 有关详细信息,请参阅 “使用类型动态”。

在 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 函数。 有关详细信息,请参阅 动态语言运行时概述

Note

如果你有一个简单的方案,需要一个对象,该对象只能在运行时添加和删除成员,但不需要定义特定操作,并且没有静态成员,请使用该 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 类可以重写此方法,以指定运算的动态行为,例如求反、递增或递减。

适用于