zoukankan      html  css  js  c++  java
  • 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的相互转换源代码

  • 相关阅读:
    app测试更多机型系统解决方法
    Dsyy的第一篇博文~
    linux服务器下安装node
    android UI进阶之实现listview的下拉加载
    android应用开发全程实录用户界面部分章节你真的会用最简单的TextView么?
    android应用开发全程实录你有多熟悉listview?
    android应用开发全程实录实现甩动拨打和挂断电话
    android应用开发全程实录关于google map的部分章节漂亮的气泡地图
    android UI进阶之用ViewPager实现欢迎引导页面
    android UI进阶之实现listview中checkbox的多选与记录
  • 原文地址:https://www.cnblogs.com/jasenkin/p/dynamic_xml_inter_exchanging.html
Copyright © 2011-2022 走看看