dynamic与xml的相互转换

     项目中很多地方采用dynamic新特性进行开发,因此本人参看了很多关于dynamic的资料。在新的一年开始,记录下自己的学习经验。

     dynamic关键字用于声明一个动态对象,然后通过该动态对象去调用方法或读写属性。

(一)测试提供的参考资料

参考http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx ,因此对该地址的博文中DynamicXMLNode类进行相应的学习与测试。测试如下:

1  static void Main(string[] args)
2         {
3             //正常运行
4             RunDynamicXMLNode(true);
5             //异常运行
6             RunDynamicXMLNode(false);
7 
8            Console.ReadLine();
9         }
 1  private static void RunDynamicXMLNode(bool state)
 2         {
 3             Console.WriteLine("------RUN begin------");
 4             try
 5             {
 6                 dynamic contact = new DynamicXMLNode("Contacts");
 7                 contact.Name = "Patrick Hines";
 8                 if (state)
 9                 {
10                     contact.Address = new DynamicXMLNode();
11                 }
12                 contact.Address.Street = "123 Main St";
13             }
14             catch (RuntimeBinderException ex)
15             {
16                 Console.WriteLine(ex.Message);
17             }
18             Console.WriteLine("------RUN end--------");
19         }

运行后显示结果如下:

 

设置断点进行单步调试,发现TryGetMember方法中:如果当前元素XElement下没有相应的XName的子元素,那么result = null;

正常运行contact.Address = new DynamicXMLNode();创建了一个新的dynamic对象。反之,contact.Address =null;将导致RuntimeBinderException异常。

 1   public override bool TryGetMember(GetMemberBinder binder, out object result)
 2         {
 3             XElement getNode = node.Element(binder.Name);
 4             if (getNode != null)
 5             {
 6                 result = new DynamicXMLNode(getNode);
 7                 return true;
 8             }
 9             else
10             {
11                 result = null;
12                 return false;
13             }
14         }

(二)对以上的类进行相应的修改

 因此本人将之进行相应的改进,result = new DynamicXElement(binder.Name);  当无法找到匹配的XElement时,返回一个新的DynamicXElement对象。改动如下:

 1 public override bool TryGetMember(
 2             GetMemberBinder binder, out object result)
 3         {
 4             XElement getNode = this.XContent.Element(binder.Name);
 5             if (getNode != null)
 6             {
 7                 result = new DynamicXElement(getNode);
 8             }
 9             else
10             {
11                 result = new DynamicXElement(binder.Name);            
12             } 
13             return true;
14         }
1  private static void RunDynamicXElement()
2         {
3             Console.WriteLine("----RunDynamicXElement begin-----");
4             dynamic contact = new DynamicXElement("Contacts");
5             contact.Name = "Patrick Hines";
6             contact.Address.Street = "123 Main St";
7             Console.WriteLine("----RunDynamicXElement end-----");
8         }

因此,contact.Address.Street = "123 Main St";这句将会创建一个新的DynamicXElement对象,参数为"Address",此处将不再抛出RuntimeBinderException异常。

 

(三)定义一个DynamicHelper类,实现dynamic对象与XML之间的互换操作

 自定义一个DynamicHelper类,主要是实现dynamic对象与XML之间的互换操作。

ToXml(dynamic dynamicObject)将传入的dynamicObject转换为xml。

ToObject(string xml, dynamic dynamicResult) 将传入的string,先转换成XElement元素,然后再构建一个DynamicXElement对象,返回结果。

ToObject(string xml)直接将xml转换为DynamicXElement对象。

 1 public class DynamicHelper
 2     {
 3         public static string ToXml(dynamic dynamicObject)
 4         {
 5             DynamicXElement xmlNode = dynamicObject;
 6             return xmlNode.XContent.ToString();
 7         }
 8 
 9         public static dynamic ToObject(string xml, dynamic dynamicResult) 
10         {
11             XElement element = XElement.Parse(xml);
12             dynamicResult = new DynamicXElement(element);
13             return dynamicResult;
14         }
15 
16         public static dynamic ToObject(string xml)
17         {
18             XElement element = XElement.Parse(xml);
19             dynamic dynamicResult = new DynamicXElement(element);
20             return dynamicResult;
21         }
22     }

为了实现ToXml()方法,修改DynamicXElement类,将私有变量node设置为属性XContent(并且设置set 方法为私有的)。这里,主要是为了获取XElement的所有内容而改进的。设置后的DynamicXElement类如下:

DynamicXElement 代码
 1  public class DynamicXElement : DynamicObject
 2     {
 3         public DynamicXElement(XElement node)
 4         {
 5             this.XContent = node;
 6         }
 7 
 8         public DynamicXElement()
 9         {
10         }
11 
12         public DynamicXElement(String name)
13         {
14             this.XContent = new XElement(name);
15         }
16 
17         public XElement XContent
18         {
19             get;
20             private set;
21         }
22 
23         public override bool TrySetMember(
24             SetMemberBinder binder, object value)
25         {
26             XElement setNode = this.XContent.Element(binder.Name);
27             if (setNode != null)
28                 setNode.SetValue(value);
29             else
30             {
31                 //creates an XElement without a value.
32                 if (value.GetType() == typeof(DynamicXElement))
33                     this.XContent.Add(new XElement(binder.Name));
34                 else
35                     this.XContent.Add(new XElement(binder.Name, value));
36             }
37             return true;
38         }
39 
40         public override bool TryGetMember(
41             GetMemberBinder binder, out object result)
42         {
43             XElement getNode = this.XContent.Element(binder.Name);
44             if (getNode != null)
45             {
46                 result = new DynamicXElement(getNode);
47             }
48             else
49             {
50                 result = new DynamicXElement(binder.Name);            
51             } 
52             return true;
53         }
54 
55         public override bool TryConvert(
56     ConvertBinder binder, out object result)
57         {
58             if (binder.Type == typeof(String))
59             {
60                 result = this.XContent.Value;
61                 return true;
62             }
63             else
64             {
65                 result = null;
66                 return false;
67             }
68         }
69 }

其他的都设置好了以后,RunDynamicHelper()将验证以上的方法,对DynamicHelper中所有的方法进行相应的测试。

 1 private static void RunDynamicHelper()
 2         {
 3             //构造一个dynamic对象
 4             dynamic dynamicObject = new DynamicXElement("ImportSample");
 5 
 6             //设置XML
 7             string xml = Resources.ImportSample;
 8 
 9             //转换成为dynamic实体(赋值)  ToObject()
10             dynamic dynamicResult = DynamicHelper.ToObject(xml, dynamicObject);
11 
12             string message = dynamicResult.Import.Message;
13             Console.WriteLine(message);
14             Console.WriteLine();
15 
16             //转换成为dynamic实体(赋值)  ToObject()
17             dynamic dynamicResult2 = DynamicHelper.ToObject(xml);
18 
19             message = dynamicResult2.Import.Message;
20             Console.WriteLine(message);
21             Console.WriteLine();
22             //ToXml()
23             string xmlResult = DynamicHelper.ToXml(dynamicResult);
24             Console.WriteLine(xmlResult);
25         }

 显示结果如下:

(四)注意:对于我们添加的资源文件,需要对自动生成的.cs进行相应的修改。

资源文件自动添加之后,类以及相关的属性访问修饰符将默认设置为internal(程序集可见),因此我们必须对访问修饰符进行相应的修改,设置为public。

1 public class Resources {        
2         [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance""CA1811:AvoidUncalledPrivateCode")]
3         internal Resources() {
4         }        
5         public static string ImportSample {
6             get {
7                 return ResourceManager.GetString("ImportSample", resourceCulture);
8             }
9         }

参考文献如下:

http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx

http://dlr.codeplex.com/ 

http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

http://blogs.msdn.com/b/csharpfaq/archive/tags/dlr/

http://blog.zhaojie.me/tag/dynamic/
http://blog.zhaojie.me/2009/10/implement-ruby-markup-builder-in-20-lines-of-c-sharp-codes.html
http://blog.zhaojie.me/2010/05/generate-dynamic-method-with-expression-tree-in-dot-net-4.html

源代码下载地址:Dynamic与xml的相互转换源代码

原文地址:https://www.cnblogs.com/jasenkin/p/dynamic_xml_inter_exchanging.html