在上两篇文章中我们已经介绍了使用ExpandoObject进行动态编程,同时也使用了ExpandoObject操作xml。本片文章就说下DynamicObject的基本使用。
概述
DynamicObject跟ExpandoObject最大的区别就是,我们可以通过继承DynamicObject,自己来决定动态对象如何执行。我们先来看下DynamicObject的定义中初始化函数:
public class DynamicObject : IDynamicMetaObjectProvider { protected DynamicObject(); }
可以看到的是我们不可以对DynamicObject直接实例化的,这也是DynamicObject设计的初衷,由我们自己来定义运行时的动态的成员的处理。一般的时候如果我们自定义的类型只需要处理一些动态的属性的时候我们只需要重写TryGetMember跟TrySetMember方法。
示例
我们通过一个Dictionary来存放成员:
public class ExtensionDynamicObject1:DynamicObject { Dictionary<string, Object> _dic=new Dictionary<string,object>(); public override bool TryGetMember(GetMemberBinder binder, out object result) { var name = binder.Name; return _dic.TryGetValue(name,out result); } public override bool TrySetMember(SetMemberBinder binder, object value) { var name = binder.Name; _dic[name] = value; return true; } }
在上面的的ExtensionDynamicObject1中通过重写了TryGetMember跟TrySetMember方法,将获取跟设置都写入到一个Dictionary<string,Object>类型的对象中去了。
写个测试方法:
[TestMethod] public void DynamicObjectsTest() { dynamic employee = new ExtensionDynamicObject1(); employee.FirstName = "Henry"; employee.LastName = "Cui"; employee.Age = 23; Console.WriteLine("Employee's info:Name:{0},Age:{1} ", employee.FirstName + employee.LastName, employee.Age); }
我们再看在里面定义一个方法:
[TestMethod] public void DynamicObjectsTest() { dynamic employee = new ExtensionDynamicObject1(); employee.FirstName = "Henry"; employee.LastName = "Cui"; employee.SayHello = (Func<string>)(()=> { return String.Format("{0} say hello at {1}", employee.FirstName + employee.LastName, DateTime.Now.ToString()); }); employee.Age = 23; Console.WriteLine(employee.SayHello()); }
看到的结果:
下面我们看下Dynamic中的其他方法:
1)TryConvert
当我们需要对动态类型转换的时候,可以通过重写TryConvert方法来自定义我们的Convert的实现:
public override bool TryConvert(ConvertBinder binder, out object result) { //Convert String if (binder.Type==typeof(String)) { if (_dic["FirstName"] != null && _dic["LastName"] != null) result = _dic["FirstName"].ToString() + _dic["LastName"].ToString(); else result = string.Empty; return true; } //Convert Integer if (binder.Type == typeof(int)) { if (_dic["Age"] != null) result = Convert.ToInt32(_dic["Age"]); else result = 0; return true; } return base.TryConvert(binder, out result); }
测试代码:
[TestMethod] public void DynamicObjectsTest() { dynamic employee = new ExtensionDynamicObject1(); employee.FirstName = "Henry"; employee.LastName = "Cui"; employee.SayHello = (Func<string>)(()=> { return String.Format("{0} say hello at {1}", employee.FirstName + employee.LastName, DateTime.Now.ToString()); }); employee.Age = 23; var strInfo = (string)employee; var age = (int)employee; Console.WriteLine(strInfo); Console.WriteLine(age); }
结果:
2)TryBinaryOperation
我们可以通过重写TryBinaryOperation去自定义我们的操作符。下面我们实现一个+的自定义实现:
public override bool TryBinaryOperation(System.Dynamic.BinaryOperationBinder binder, object arg, out object result) { if (binder.Operation == System.Linq.Expressions.ExpressionType.Add) { var sub = new List<dynamic>(); sub.Add(this); sub.Add((dynamic)arg); result = sub; return true; } return base.TryBinaryOperation(binder, arg, out result); }
测试方法:
[TestMethod] public void DynamicObjectsTest() { dynamic employee = new ExtensionDynamicObject1(); employee.FirstName = "Henry"; employee.LastName = "Cui"; dynamic employee1 = new ExtensionDynamicObject1(); employee1.FirstName = "Hello"; employee1.LastName = "Ketty"; var list = new List<dynamic>(); list = employee + employee1; foreach (dynamic em in list) { Console.WriteLine("Employee's Name was {0}", em.FirstName + em.LastName); } }
测试结果:
我们还可以重写DynamicObject中的其他许多方法,实现我们动态运行时的操作。这里就不再举例了。
总结
本文中主要介绍了DynamicObject的基本使用,通过重写里面的方法实现我们动态运行时的自定义操作,这样我们可以更多的去实现自己一些动态的组件。下篇文章中会利用DynamicObject来实现一个Xml的操作的示例。