65.9K
CodeProject 正在变化。 阅读更多。
Home

Expando Object 介绍 - Dotnet 4.0

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.14/5 (13投票s)

2010年10月25日

CPOL

3分钟阅读

viewsIcon

37028

downloadIcon

245

这篇短文将重点介绍 Expando Object 的一些特性

引言

Dotnet 4.0 框架中另一个新增的功能是 Expando object。它在 System.Core 程序集中定义,属于 System.Dynamic 命名空间。

Intellisense 将 Expando object 描述为

1.jpg

Expando Object – 内部视图

深入了解 Expando Object 会发现以下内容

2.jpg

Expando 类不能被继承,因为它被密封了。它实现了六个不同的接口。其中,以下两个需要特别注意

IDynamicMetaObjectProvider

我们知道,任何可以在运行时绑定其操作的对象都必须实现 IDynamicMetaObjectProvider。Expando object 也是如此。

因此,dynamic dyn = new ExpandoObject(); 是一个完全有效的语句。

INotifyPropertyChanged

每当添加或修改新成员时,该类都会引发 PropertyChange 事件。

使用代码

示例 1:添加成员

考虑以下程序

dynamic dyn = new ExpandoObject();
//Members additon
dyn.Member1 = "Some Member";
dyn.Member2 = 2;
Console.WriteLine(dyn.Member1);
Console.WriteLine(dyn.Member2);

我们只是向 ExpandoObject 添加了两个成员。真的很简单。

示例 2:从 Expando 集合中读取和写入

此代码片段将展示如何向 Expando 集合赋值

List expandoList = new List();

//Writing to Expando Collection
for (int i = 2; i --> 0;)
{
  dynamic dynObject = new ExpandoObject();
  dynObject.Prop1 = i;
  dynObject.Prop2 = "String Property" + i;                
  dynObject.Prop3 = AddDictionaryObject (i);
  expandoList.Add(dynObject);
}

//Adding a dictionary object
private static Dictionary AddDictionaryObject(int i)
{
   Dictionary dict = new Dictionary();
   dict.Add(i, "Value" + i.ToString());
   return dict;
}

首先,我们实例化一个新的 ExpandoObject 集合。

列表expandoList = new List();

然后,使用新的“Goes To”运算符,我们将两个项目填充到集合中。

行 dynamic dynObject = new ExpandoObject(); 确保 ExpandoObject 被分配给动态对象,此后我们可以动态地向其添加属性,DLR 将在运行时检查这些属性。我们还有一个属性(这里是 Prop3),它的类型是 Dictionary < int, string >

代码非常直观。

下一部分展示了如何从刚刚创建的 Expando 集合中读取值

//Reading from Expando Collection

foreach (dynamic d in expandoList)
{                
   Console.WriteLine("Reading Collection {0} Values", d.Prop1);
   Console.WriteLine("Prop1 value is:   {0}",d.Prop1);
   Console.WriteLine("Prop2 value is:   {0}", d.Prop2);
   foreach (dynamic dic in d.Prop3)
   {
     Console.WriteLine("The key is {0} and it's value is {1}",dic.Key,dic.Value);
   }

  Console.WriteLine(Environment.NewLine);
  Console.WriteLine("-----------------------------------------------------------");
}

可以理解的是,我们正在循环遍历 Expando 集合,并且由于每个项目的类型都是 dynamic,我们可以简单地调用属性名称。但是,属性是否有效将在运行时进行检查。

示例 3:添加 Action 和 Func 委托

考虑以下:

情况 1:为回调添加 Action 委托

dynamic dynObj= new ExpandoObject();

//Add Action Delegate
dynObj.Action = new Action(() =>
{
   Console.WriteLine("Helo From Action Delegate");
 });
//Invoke the Action method
dynObj.Action();

不多说… 只是在运行时分配 Action 委托,并调用它进行简单的回调。

情况 2:为回调添加 Func 委托

//Add Func delegate 
dynObj.Func = new Func                
              ((a, res, str) => Calci(a,res,str));

//Invoke the Func Method
Console.WriteLine("The {0} operation yields {1}", 
				"+", dynObj.Func(12, 4, "+"));

Calci 函数在这里

private static int Calci(int num1, int num2, string op)
{
  int result = 0;
  switch (op)
  {
    case "+":
    result = num1 + num2;
     break;
     case "-":
     result = num1 - num2;
     break;
     case "*":
     result = num1 * num2;
     break;
     case "/":
     result = num1 / num2;
     break;
    }

   return result;
}

这展示了我们如何使用 Func 委托进行简单的算术运算。

示例 4:通知属性更改事件

如上所述,Expando Object 实现了 INotifyPropertyChanged 接口,该接口位于 System.ComponentModel 命名空间中。

这意味着,每当我们向 Expando Object 添加新属性或更改现有属性的值时,应该触发 PropertyChanged 事件处理程序。让我们看看如何做到这一点

dynamic dynObject = new ExpandoObject();
 ((INotifyPropertyChanged)dynObject).PropertyChanged += 
 new PropertyChangedEventHandler(Program_PropertyChanged);

dynObject.Property1 = 10;

//Now change the value
dynObject.Property1 = 20;

而 PropertyChanged 事件处理程序如下

static void Program_PropertyChanged
(
	object sender
	, PropertyChangedEventArgs e
)
{
	Console.WriteLine("Property {0} with value {1}",
					e.PropertyName, ((dynamic)sender).Property1);
}

在这里,我们只是定义了一个属性 Property1,并将初始值设置为 10。接下来,我们将属性值更改为 20。结果是

3.jpg

示例 5:处理事件

我们可以为 ExpandoObject 定义事件。

要遵循的步骤列在下面

           #region Handling Events
            dynamic dynObjectEvent = new ExpandoObject();
            //Just Adding a memeber
            dynObjectEvent.Value = 10;

            //Step 1: Add a member and set it to null first
            dynObjectEvent.customEventMember = null;
            //Step 2:Now subscribe
            dynObjectEvent.customEventMember += new EventHandler(CustomEventHandler);
            //Step 3: Raise the Event
            EventHandler eh = dynObjectEvent.customEventMember;
            if (eh != null) eh.Invoke(dynObjectEvent, EventArgs.Empty);
           //or eh(dynObjectEvent, EventArgs.Empty);

            #endregion  

事件处理程序定义如下

static void CustomEventHandler(object sender, EventArgs e)
{          
 Console.WriteLine("Custom event handler raised by {0} and has send a value {1}",
                ((dynamic)sender).customEventMember
                , ((dynamic)sender).Value);
}

可以看出,定义事件是一个三步过程。

步骤 1: 添加一个成员,并首先将其设置为 null

 dynObjectEvent.customEventMember = null;

步骤 2: 现在订阅事件

dynObjectEvent.customEventMember 
	+= new EventHandler(CustomEventHandler);

步骤 3: 触发事件

 EventHandler eh = dynObjectEvent.customEventMember;
 if (eh != null) eh.Invoke(dynObjectEvent, EventArgs.Empty);
 

输出为:

6.jpg

结论

在这个简短的教程中,我们已经看到了 Expando Object 的一些好处。

非常感谢您对该主题的评论,以便改进该主题。

感谢阅读本文。

© . All rights reserved.