DynamicObject 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
提供用于在运行时指定动态行为的基类。 此类必须继承自;无法直接实例化它。
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) 的对象,并重写 TrySetMember 和 TryGetMember 方法以支持新语法。 它还提供一个 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 。 |