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类如下:

ExpandedBlockStart.gif 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的相互转换源代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值