.Net 4.0 DynamicObject使用(下)
2010-07-11 18:44 Henry Cui 阅读(4210) 评论(0) 收藏 举报在上篇文章中我们看过了DynamicObject的基本使用,这篇文章中我们通过Dynamic来实现一个操作xml的动态类型,让我们更为方便的操作xml。
其实在前面的使用ExpandoObject的文章中我们已经,通过ExpandoObject来实现了操作Xml,并体现了动态性,但是不好的是,里面没有Linq to Xml大量Api的支持,操作起来很不方便,同时我们需要编写大量的辅助方法才行。而DynamicObject可以让我们自己决定动态运行时的操作方式,我们可以很快想到通过借助XElement来实现。是的,我的想法就是这样的。
基本实现
来看看我们的Linq to Xml的语法:
var employee = new XElement(
"Employee",
new XElement("Name",
new XElement("FirstName","Henry"),
new XElement("LastName","Cui")),
new XElement("Birthday","1987-10-14")
);
现在我们可以借助DynamicObject来实现一种更为直观更为简洁的语法的创建Xml的方式。
首先我们来顶一个DynamicXNode类型,继承于DynamicObject:
public class DynamicXNode:DynamicObject
{
private XElement _XElement;
#region Constructor Methods
public DynamicXNode(string name)
{
_XElement = new XElement(name);
}
public DynamicXNode(XElement node)
{
_XElement = node;
}
#endregion
}
我们来重写下TryGetMember 跟TrySetMember方法:
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var node = _XElement.Element(binder.Name);
if (node != null)
{
result = new DynamicXNode(node);
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var node = _XElement.Element(binder.Name);
if (node != null)
{
node.SetValue(value);
}
else
{
//是否是复合的类型
if (value is DynamicXNode)
{
_XElement.Add(new XElement(binder.Name));
}
else
{
_XElement.Add(new XElement(binder.Name, value.ToString()));
}
}
return true;
}
我们来写测试的代码看:
[TestMethod()]
public void DynamicXNodesTest()
{
dynamic employee = new DynamicXNode("Employee");
employee.Name = new DynamicXNode("Name");
employee.Name.FirstName = "Henry";
employee.Name.LastName = "Cui";
employee.Birthday = "1987-10-14";
}
哦,我们还需要借助XElement来把它输出来,在重写下TryConvert方法吧:
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type.Equals(typeof(XElement)))
{
result = _XElement;
return true;
}
return base.TryConvert(binder, out result);
}
之后我们输出来可以看到:
添加额外的东西
好像已经差不多了,可是我们这里还没有Api的支持啊,我们可以将动态的方法的Invoke通过XElement去Invoke,重写
TryInvokeMember,通过反射机制到XElement上执行吧:
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var ttype = typeof(XElement);
try
{
result = ttype.InvokeMember(binder.Name,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null,
_XElement,
args);
return true;
}
catch
{
result = null;
return false;
}
}
总结
在这篇文章中我们看到了如果使用DynamicObject进行应用了,这里面只是一个xml操作的一个想法,还有许多需要去完善的地方。在.Net4.0中的动态性确实给我们带来了很大的惊喜,已经方便之处。参考文档
Dynamic in C# 4.0: Creating Wrappers with DynamicObject http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx
浙公网安备 33010602011771号