您的位置:首页 > 移动开发 > Objective-C

ExpandoObject DynamicObject 的用法

2017-10-12 10:36 218 查看
As you know, the ExpandoObject class implements the IDictionary<string, object> interface, so if you have an ExpandoObject you can easily cast it to an IDictionary< but there’s no built-in way to easily do the reverse.

Luckily, I came across a very useful extension method today which converts an IDictionary<into an ExpandoObject, which you can then use dynamically in your code, sweet! :-)

With some small modifications, here’s the code I ended up with, with some comments thrown in for good measures:

/// <summary>
/// Extension method that turns a dictionary of string and object to an ExpandoObject
/// Snagged from http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/ /// </summary>
public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;

// go through the items in the dictionary and copy over the key value pairs)
foreach (var kvp in dictionary)
{
// if the value can also be turned into an ExpandoObject, then do it!
if (kvp.Value is IDictionary<string, object>)
{
var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key, expandoValue);
}
else if (kvp.Value is ICollection)
{
// iterate through the collection and convert any strin-object dictionaries
// along the way into expando objects
var itemList = new List<object>();
foreach (var item in (ICollection)kvp.Value)
{
if (item is IDictionary<string, object>)
{
var expandoItem = ((IDictionary<string, object>)item).ToExpando();
itemList.Add(expandoItem);
}
else
{
itemList.Add(item);
}
}

expandoDic.Add(kvp.Key, itemList);
}
else
{
expandoDic.Add(kvp);
}
}

return expando;
}


DynamicObject和ExpandoObject

1.ExpandoObject表示一个对象,该对象包含可在运行时动态添加和移除的成员.这个类和动态类型有关,这个类能做些什么?

案例:

//ExpandoObject这个类需要引入System.Dynamic;
dynamic dynEO = new ExpandoObject();
dynEO.number = 20;
dynEO.Method = new Func<int, string>((int i) => { return (i + 20).ToString(); });
Console.WriteLine(dynEO.number);
Console.WriteLine(dynEO.Method(dynEO.number));
Console.ReadKey();


ExpandoObject这个累还是很有用的,他可以动态的添加成员和方法,这样我们就可以在写一些对象时,不需要在new一个class那么麻烦,只要这个类就OK了,不过有一点要注意,这个类时在运行时解析的,这样我们就会带来性能上的一些损失,而且,程序的逻辑复杂性越高,越难发现问题所在,所以,对于简单的对象,我们可以使用这个类,复杂的就不要使用了.

2.DynamicObject

DynamicObject跟ExpandoObject最大的区别就是,我们可以通过继承DynamicObject,自己来决定动态对象如何执行.咱先来看一下DynamicObject的定义中初始化函数:

public class DynamicObject:IDynamicObjectProvider
{
protected DynamicObject();
}


可以看到的是我们不可以对DynamicObject直接实例化,这也是DynamicObject设计的初衷,有我们自己来决定运行时的动态的成员的处理.一般的时候如果我们自定义的类型只需要处理一些动态的属性的时候我们只需要重写TryGetMember和TrySetMember这两个方法.

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dynamic和Expando
{
class Program
{
static void Main(string[] args)
{
dynamic employee = new Test();
employee.Name = "zhangsan";
employee.Age = "22";
employee.Sex = "Man";
Console.WriteLine("name : {0} , age = {1} , sex = {2}",employee.Name,employee.Age,employee.Sex);
Console.ReadKey();
}
}
public class Test : DynamicObject
{
Dictionary<string, object> dic = new Dictionary<string, object>();

/*
* 这里重写TryGetMember和TrySetMember方法,继承了DynamicObject后,
* 可以override一大堆TryXXX的方法了
*/
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var name = binder.Name;
Console.WriteLine("获取 {0}",name);
return dic.TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var name = binder.Name;
dic[name] = value;
Console.WriteLine("写入 {0} = {1}",name,value);
return true;
}
}
}


我们还可以重写DynamicObject中的其他许多方法,实现我们动态运行时的操作.通过重写里面的方法实现我们动态运行时的自定义操作,这样我们可以更多的趋势线自己的一些动态的组件.

我是个比较啰嗦的人,我觉得有必要去分析一下冲下的那两个方法:TryGetMember和TrySetMember

TrySetMember方法:为设置成员值的操作提供实现.从DynamicObject类派生的类可以重写此方法,以便为诸如设置属性值这样的操作指定动态行为.

TryGetMember方法:提供了实现的操作得到成员的值.继承DynamicObject的类可以覆盖这个方法来制定动态行为等操作得到一个属性的值.

简单说,TryGetMember得到值,TrySetMember设置值.

TryGetMember(GetMemberBinder binder, out object result) 方法实现对数据的获取,binder.Name就是获取的属性的名称,result是获取的属性值.通过binder.Name在Data中获取到对应的属性值,传出到外面(能看到result是out参数)

TrySetMember(SetMemberBinder binder, object value) 对存在的属性进行赋值.

http://blog.csdn.net/shanyongxu/article/details/47300187
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: