dynamic对象是什么
MSDN上说:
提供用于在运行时指定动态行为的基类。 必须继承此类;不能直接对其进行实例化。
dynamic的意义
dynamic的出现不同凡响,它在.net里在相当程度上取代了“反射”的机制,有了它,你就不用写复杂的反射代码了!
dynamic类的属性取值赋值
MSDN中提到一点:“必须继承此类;不能直接对其进行实例化。”
所以我们经常用到的是它的“继承类”ExpandoObject,而我们的问题“给dynamic对象属性取值赋值”可以变成“给ExpandoObject对象属性取值赋值”。
当然,dynamic 跟 dynamicObject没有直接联系。实际上还有 dynamicMetaObject 等等新的类,不能把名称看错。dynamic 关键字是个“语法糖”,它可以用来引用 ExpandoObject对象,DynamicObject 对象,也可以引用其它成千上万种对象。它就是用来避免你写反射代码的。
……
以ExpandoObject 对象来讲,“一句话”就能说明功能要点:ExpandoObject 对象实现了 IDictionary<string,object> 接口,通过它进行属性的动态处理(包括增加、删除属性等等操作)。
还不知道是什么吧?那直接以代码来说明吧:
dynamic o = new ExpandoObject();
o.name="yes";
var dic = (IDictionary<string,object>)o;
dic["name"]="ok";
怎么样,是不是很简单?
ExpandoObject
MSDN上说:
可在运行时动态添加和删除其成员的对象
public sealed class ExpandoObject : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string,object>>, System.Collections.Generic.IDictionary<string,object>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,object>>, System.ComponentModel.INotifyPropertyChanged, System.Dynamic.IDynamicMetaObjectProvider
注解
ExpandoObject
类使你能够在运行时添加和删除其实例的成员,还可以设置和获取这些成员的值。 此类支持动态绑定,使你可以使用类似的标准语法, sampleObject.sampleMember
而不是更复杂的语法 sampleObject.GetAttribute("sampleMember")
。
ExpandoObject
类实现 (DLR) 接口的标准动态语言运行时 IDynamicMetaObjectProvider ,这使你能够在 ExpandoObject
支持 DLR 互操作性模型的语言之间共享类的实例。 例如,可以使用 c # 创建类的实例 ExpandoObject
,然后将其传递给 IronPython 函数。 有关详细信息,请参阅 c # 常见问题网站上的 动态语言运行时概述 和 介绍 ExpandoObject 。
ExpandoObject
类是动态对象概念的实现,它允许获取、设置和调用成员。 如果要定义具有其自己的动态调度语义的类型,请使用 DynamicObject 类。 如果希望定义动态对象如何参与互操作性协议并管理 DLR 快速动态调度缓存,请创建自己的 IDynamicMetaObjectProvider 接口实现。
创建实例
在 c # 中,若要为类的实例启用后期绑定 ExpandoObject
,必须使用 dynamic
关键字。 有关更多信息,请参见使用类型 dynamic。
在 Visual Basic 中,后期绑定支持动态操作。 有关详细信息,请参阅 Visual Basic) 的早期和后期绑定 (。
下面的代码示例演示如何创建类的实例 ExpandoObject
。
dynamic sampleObject = 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
方法表示存储为委托的 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
下面的代码示例演示如何将事件添加到类的实例 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.
作为参数传递
可以将类的实例 ExpandoObject
作为参数传递。 请注意,在 Visual Basic 中,这些实例被视为 c # 中的动态对象和后期绑定的对象。 这意味着你没有对象成员的 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.
枚举和删除成员
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
在不具有删除成员 (如 c # 和 Visual Basic) 的语法的语言中,可以通过将的实例隐式强制转换 ExpandoObject
为 IDictionary<String, Object>
接口,然后将该成员作为键/值对删除,来删除成员。 下面的示例说明了这一点。
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).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);
}
}