DynamicXml -- 动态读取操作XML (一个从XML到Object的通用实现)
2011-12-14 04:18
405 查看
最近的一个项目用到很多不同结构的XML文件. 于是就在网上搜索了一些文章, 结合实际遇到的问题写成自己要的代码.
既然已经获取了这方面的知识,不敢独取, 拿出来共享. 这个也还不是很成熟, 希望大家共同完善, 提出宝贵意见, 共同进步.
或者是类似任意结构的XML文件, 可以实现初始化
dynamic dx = new DynamicXml(xml);
并且读取属性值:
dx.books.book[0].author, dx.books.book[2].price
那么就从这个类中继承生成子类, 同时也需要实现 IEnumerable.
稍微介绍一下:
DynamicObject 类使您能够定义可以动态对象上执行哪些操作以及如何执行这些操作。
如果只需要设置和获取属性的操作,您可以只覆盖 TrySetMember 和 TryGetMember 方法。
IEnumerable 公开枚举器,该枚举器支持在非泛型集合上进行简单迭代。
应该大家都知道要实现自定义集合的IEnumerable 就要完成
public IEnumerator GetEnumerator()
也就是说, 为了实现需求, 至少我们需要完成三个函数:
TrySetMember, TryGetMember, GetEnumerator
public class DynamicXml : DynamicObject, IEnumerable
{
public DynamicXml(string text)
{
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
}
public IEnumerator GetEnumerator()
{
}
}
在构造函数里我们希望可以读取XML的内容, 加载所有元素的值.
在TrySetMember中, 我们为设置成员值的操作提供实现, 以便为设置属性值指定动态行为。在本文中, 我们只考虑读取XML内容, 所以不需要重写这个函数.
在TryGetMember中, 我们要为获取成员值的操作提供实现。
在 TryGetIndex中, 我们要为按索引获取值的操作提供实现.
实现的代码如下:
[/code]
我把print函数专门拿出来, 故弄玄虚一下, 因为两个XML的结构有类似的地方, 所以可以同时使用下面的函数. -- 当然对于这样的情况,我们也可以为此定义一个interface.
[/code]
不是什么很深奥的东西, 但是希望可以为有同样问题的朋友们节省一些时间.
如果可以较好的掌握Dynamic, 可以节省一些反射方面的代码. 不过这是另外一个话题了.
本文来自于喜乐的ASP.NET(Alex Song) 转贴请注明出处
参考文章:
既然已经获取了这方面的知识,不敢独取, 拿出来共享. 这个也还不是很成熟, 希望大家共同完善, 提出宝贵意见, 共同进步.
目标
基于已经有的XML文件,例如:<root> <books> <book> <author>John Savacki</author> <title>E.G.Title</title> <price>20.50</price> </book> <book> <author>Tom Curly</author> <title>E.G.Title 2</title> <price>26.50</price> </book> </books> </root>
或者是类似任意结构的XML文件, 可以实现初始化
dynamic dx = new DynamicXml(xml);
并且读取属性值:
dx.books.book[0].author, dx.books.book[2].price
解决方案
自然是选择C# 4.0 中引入的 DynamicObject, 关键是已有的.net框架中不能提供这样的功能.那么就从这个类中继承生成子类, 同时也需要实现 IEnumerable.
稍微介绍一下:
DynamicObject 类使您能够定义可以动态对象上执行哪些操作以及如何执行这些操作。
如果只需要设置和获取属性的操作,您可以只覆盖 TrySetMember 和 TryGetMember 方法。
IEnumerable 公开枚举器,该枚举器支持在非泛型集合上进行简单迭代。
应该大家都知道要实现自定义集合的IEnumerable 就要完成
public IEnumerator GetEnumerator()
也就是说, 为了实现需求, 至少我们需要完成三个函数:
TrySetMember, TryGetMember, GetEnumerator
实现
通过上面的分析, 我们知道这个类看起来应该是这样:public class DynamicXml : DynamicObject, IEnumerable
{
public DynamicXml(string text)
{
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
}
public IEnumerator GetEnumerator()
{
}
}
在构造函数里我们希望可以读取XML的内容, 加载所有元素的值.
在TrySetMember中, 我们为设置成员值的操作提供实现, 以便为设置属性值指定动态行为。在本文中, 我们只考虑读取XML内容, 所以不需要重写这个函数.
在TryGetMember中, 我们要为获取成员值的操作提供实现。
在 TryGetIndex中, 我们要为按索引获取值的操作提供实现.
实现的代码如下:
[code] public class DynamicXml : DynamicObject, IEnumerable { private readonly List<XElement> _elements; public DynamicXml(string text) { var doc = XDocument.Parse(text); _elements = new List<XElement> { doc.Root }; } protected DynamicXml(XElement element) { _elements = new List<XElement> { element }; } protected DynamicXml(IEnumerable<XElement> elements) { _elements = new List<XElement>(elements); } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = null; if (binder.Name == "Value") result = _elements[0].Value; else if (binder.Name == "Count") result = _elements.Count; else { var attr = _elements[0].Attribute( XName.Get(binder.Name)); if (attr != null) result = attr; else { var items = _elements.Descendants( XName.Get(binder.Name)); if (items == null || items.Count() == 0) return false; result = new DynamicXml(items); } } return true; } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { int ndx = (int)indexes[0]; result = new DynamicXml(_elements[ndx]); return true; } public IEnumerator GetEnumerator() { foreach (var element in _elements) yield return new DynamicXml(element); } }
[/code]
运用
在具体运用中, 有些地方是非常有趣的, 因为我们有了dynamic, 所以你可以用同一个变量去获取不同结构的XML文件. 运用代码如下:
static void Main(string[] args)
{
string xml = @"<root> <books> <book> <author>John Savacki</author> <title>E.G.Title</title> <price>20.50</price> </book> <book> <author>Tom Curly</author> <title>E.G.Title 2</title> <price>26.50</price> </book> </books> </root>";
dynamic dx = new DynamicXml(xml);
Console.WriteLine("----- Book List -----");
foreach (dynamic b in dx.books.book)
{
Console.WriteLine("author='{0}'", b.author.Value);
print(b);
}
Console.WriteLine("------ Book List End ------");
string xml2 = @"<root>
<products>
<product>
<title>iPhone 4</title>
<price>2222.50</price>
<quantity>10</quantity>
</product>
<product>
<title>Lenovo IdeaPad</title>
<price>5432.50</price>
<quantity>15</quantity>
</product>
</products>
</root>";
dx = new DynamicXml(xml2);
Console.WriteLine("----- Product List -----");
foreach (dynamic b in dx.products.product)
{
Console.WriteLine("quantity='{0}'", b.quantity.Value);
print(b);
}
Console.WriteLine("------ Product List End ------");
Console.Read();
}
我把print函数专门拿出来, 故弄玄虚一下, 因为两个XML的结构有类似的地方, 所以可以同时使用下面的函数. -- 当然对于这样的情况,我们也可以为此定义一个interface.
[code] static void print(dynamic b) { Console.WriteLine("Title='{0}'", b.title.Value); Console.WriteLine("price='{0}'", b.price.Value); }
[/code]
不是什么很深奥的东西, 但是希望可以为有同样问题的朋友们节省一些时间.
如果可以较好的掌握Dynamic, 可以节省一些反射方面的代码. 不过这是另外一个话题了.
本文来自于喜乐的ASP.NET(Alex Song) 转贴请注明出处
参考文章:
Dynamic XML
Fluent XML Parsing Using C#'s Dynamic Type Part 1 | CapTech ...相关文章推荐
- DynamicXml -- 动态读取操作XML (一个从XML到Object的通用实现)
- DynamicXml -- 动态读取操作XML (一个从XML到Object的通用实现)
- C#DynamicXml动态读取操作XML(XML到Object的通用实现)
- 这是一个关于XML文档的操作管理器XMLHelper类,类中包括XML文档的创建,文档节点和属性的读取,添加,修改,删除的方法功能的实现
- XML解析器可以读取、更新、创建、操作一个XML文档
- 一个用 C# 实现操作 XML 文件的公共类代码
- 实现动态的XML文件读写操作(依然带干货)
- c#读取XML内容实现动态加载菜单
- 从HBase数据库表中读取数据动态转为DataFrame格式,方便后续用Spark SQL操作(scala实现)
- POI实现一个通用的Excel读取模板
- 用JS读取.txt文件方法以及一个操作.txt文件通用类方法【深海原创】
- C#——通过XML读取左侧菜单实现Extjs菜单动态加载
- 实现动态的XML文件读写操作(依然带干货)
- 定义一个 GlobalSqlConfigHelper 类,实现读取 XML 文件中的 SQL 语句。
- 一个通用的单元测试框架的思考和设计09-实现篇-视图操作
- 一个通用的单元测试框架的思考和设计09-实现篇-视图操作
- 实现动态的XML文件读写操作(依然带干货)
- 动态创建表格js文件,javascript,Ajax,DHTML动态实现表格的创建,动态读取XML中的文件,读取dom节点的例子。
- JAVA操作XML一(读取):使用DOM读取XML数据的两种具体实现
- [每天一个demo]用c#实现简单的xml操作代码