C# - DynamicObject with Dynamic
本文转载:http://joe-bq-wang.iteye.com/blog/1872756
里面有动态Linq to xml的写法。
There is a expando object which allow you add/remove properties at runtime, DynamicObject provides ou with more capability and it is better used in places where a wrapper excels a raw XML file or script object syntax.
First, we will intoduce the DynamicObject, as stated in the References Section on "DynamicObject Class",which defines some methods such as TryGetMember, TrySetMember, TryInvokeMembers which acts as a proxy to the real value contained in the DynamicObject derived classes. Also, DynamicObject has special support from the DLR (Dynamic Language Runtime) which means it has some special translation when you use DynamicObject with "dynamic" keyword.
First, we will see a example object with DynamicObject which has the ability to let you query/set values in case-insensitive fashion, which the real data is backed by a Dictionary.
- using System.Collections.Generic;
- using System.Dynamic;
- namespace DynamicObjectDemo
- {
- class DynamicDictionary : DynamicObject
- {
- private Dictionary<string, object> dictionary = new Dictionary<string, object>();
- public int Count
- {
- get { return dictionary.Count; }
- }
- public override bool TryGetMember(GetMemberBinder binder, out object result)
- {
- string name = binder.Name.ToLower();
- return dictionary.TryGetValue(name, out result);
- }
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- dictionary[binder.Name.ToLower()] = value;
- return true;
- }
- }
- }
and here is a test program to show you how to use the DynamicDictionary class.
- namespace DynamicObjectDemo
- {
- /// <summary>
- /// Main method to test the DynamicObject
- /// </summary>
- /// <remarks>
- /// <para>
- /// Please find references information from: http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx
- /// </para>
- /// </remarks>
- class Program
- {
- static void Main(string[] args)
- {
- // you must use the "Dynamic" keyword to create object, otherwise, you won't be able to use get the dynamic behavior
- dynamic person = new DynamicDictionary();
- // adding new Dictionary Properties
- person.FirstName = "Ellen"; // the dynamic language runtime (DLR) first uses the language binder to look for a static definition of a property in the class. If there is no such property, the DLR calls the TrySetMember method.
- person.LastName = "Adams";
- //getting values of the dynamic properties
- // the tryGetMember methods is called
- Console.WriteLine(person.FirstName + " " + person.lastname); // this time, we uses the lower case member
- Console.WriteLine("NUmber of dynamic properties" + person.Count);
- try
- {
- // the following will throw Exception at runtime,
- // when the TryGetMember method return a false, and this causes a
- // RuntimeBinderException
- Console.WriteLine(person.address);
- }
- catch (RuntimeBinderException ex)
- {
- Debug.WriteLine("caught exception calling person.address: {0}", ex.ToString());
- }
- catch (Exception ex)
- {
- Debug.WriteLine("Some unknown exception : {0}", ex.ToString());
- }
- }
- }
- }
With DynamicObject, you can do even more, suppose that we have an XElement and we know we can create an XElement with some syntax as below.
- XElement contactXML =
- new XElement("Contact",
- new XElement("Name", "Patrick Hines"),
- new XElement("Phone", "206-555-0144"),
- new XElement("Address",
- new XElement("Street1", "123 Main St"),
- new XElement("City", "Mercer Island"),
- new XElement("State", "WA"),
- new XElement("Postal", "68042")
- )
- );
however, we can make it even simpler. what we have in mind is something like this:
- dynamic contact = new DynamicXMLNode("Contacts");
- contact.Name = "Patrick Hines";
- contact.Phone = "206-555-0144";
- contact.Address = new DynamicXMLNode();
- contact.Address.Street = "123 Main St";
- contact.Address.City = "Mercer Island";
- contact.Address.State = "WA";
- contact.Address.Postal = "68402";
we might need to write Dyanmic Extended class with the following override.s
TryGetMember : the Contact.Address.Street part in the Contact.Address.Street statement (the part to get some member back)
TrySetMember: contact.Name = "Patrick Hines";
TryConvert: contact.Name = "Patrick Hines"; (Expected value type is String, but returned type is a DynamicXMLNode)
TryInvokeMember: we have hide the XElement , this enables us to the hidden methods supported by the Xlement
here is the full code of the implementation of DynamicXMLNode.
- using System;
- using System.Dynamic;
- using System.Reflection;
- using System.Xml.Linq;
- namespace DynamicObjectDemo
- {
- /// <summary>
- /// A wrapper on the XElement
- /// </summary>
- /// <remarks>
- /// <para>
- /// You can find some reference page from
- /// * 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
- /// </para>
- /// </remarks>
- public class DynamicXMLNode : DynamicObject
- {
- XElement node;
- public DynamicXMLNode(XElement node)
- {
- this.node = node;
- }
- public DynamicXMLNode()
- {
- }
- public DynamicXMLNode(string name)
- {
- node =new XElement(name);
- }
- public override bool TryGetMember(GetMemberBinder binder, out object result)
- {
- XElement getNode = node.Element(binder.Name);
- if (getNode != null)
- {
- result = new DynamicXMLNode(getNode);
- return true;
- }
- else
- {
- result = null;
- return false;
- }
- }
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- XElement setNode = node.Element(binder.Name);
- if (setNode != null)
- {
- setNode.SetValue(binder.Name);
- }
- else
- {
- if (value.GetType() == typeof (DynamicXMLNode))
- {
- node.Add(new XElement(binder.Name));
- }
- else
- {
- node.Add(new XElement(binder.Name, value));
- }
- }
- return true;
- }
- // TryGetMember always returns an instance of DynamicXMLNode. How do I get the actual value of the XML node? For example, I want the following line to work, but now it throws an exception.
- // String state = contact.Address.State
- // one option is to return the actual values for leaf nodes, but to explore another option: you can try the type conversion, just add the following method to the DynaxmicXMLNode class
- public override bool TryConvert(ConvertBinder binder, out object result)
- {
- if (binder.Type == typeof(string))
- {
- result = node.Value;
- return true;
- }
- else
- {
- result = null;
- return false;
- }
- }
- // though we can get manipulate indirectly to XElement values wrapped by the DynamicXMLNode, we can even get the contained result
- // out of the DynamicXMLNode, we cannot call methods which is suppose to work on XElement, here is what in addition you can
- // to get Access to XElement methods
- public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
- {
- Type xmlType = typeof(XElement);
- try
- {
- result = xmlType.InvokeMember(binder.Name,
- BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
- null,
- node,
- args);
- return true;
- }
- catch
- {
- result = null;
- return false;
- }
- }
- }
- }
to give an impression on the capability that the DynamixXMLNode has empowered us, let 'see the test code below.
- public class DynamicXMLNodeMain
- {
- public static void DynamicXMLNodeCreateReturnValidDynamixXMLNode()
- {
- dynamic contact = CreateDynamicXMLNode();
- if (contact != null)
- {
- Console.WriteLine("Created DynamicXMLNode ");
- }
- else
- {
- Console.WriteLine("Failed to create DynamicXMLNode");
- }
- }
- public static void DynamicXMLNodeConvertToStringReturnXElementValue()
- {
- dynamic contact = CreateDynamicXMLNode();
- string state = contact.Address.State;
- Console.WriteLine("State is {0}", state);
- }
- public static void DynamicXMLNodeTryInvokeMemberCallXElementMethods()
- {
- dynamic contact = CreateDynamicXMLNode();
- contact.Address.Postal.SetValue("newPostValue");
- string newPostal = contact.Address.Postal;
- if (newPostal == "newPostValue")
- {
- Console.WriteLine("Set new Post value");
- }
- else
- {
- Console.WriteLine("Failed to set new postal value");
- }
- }
- public static DynamicXMLNode CreateDynamicXMLNode()
- {
- dynamic contact = new DynamicXMLNode("Contacts");
- contact.Name = "Patrick Hines";
- contact.Phone = "206-555-0144";
- contact.Address = new DynamicXMLNode();
- contact.Address.Street = "123 Main St.";
- contact.Address.City = "Mercer Island";
- contact.Address.State = "NA";
- contact.Address.Postal = "68402";
- return contact;
- }
- }
and this is the Main method which invoke them..
- static void Main(string[] args)
- {
- // This is test on the DynamicXMLNode
- DynamicXMLNodeMain.DynamicXMLNodeCreateReturnValidDynamixXMLNode();
- DynamicXMLNodeMain.DynamicXMLNodeConvertToStringReturnXElementValue();
- DynamicXMLNodeMain.DynamicXMLNodeTryInvokeMemberCallXElementMethods();
- }
C# - DynamicObject with Dynamic的更多相关文章
- C# DynamicObject 动态对象
dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你 ...
- dynamic解析Http xml格式响应数据
继续上一篇 构建RESTful风格的WCF服务 ,咱已经把服务端的数据和服务准备好了,客户端调用 wcf rest接口后如何解析xml?下面使用dynamic关键字解析来至于WCF REST XML响 ...
- 理解C# 4 dynamic(3) – DynamicObject的使用
上篇文章"理解C# 4 dynamic(2) – ExpandoObject的使用" 了解了ExpandoObject的基本使用. 但ExpandoObject的问题就是它是一个万 ...
- 浅谈Dynamic 关键字系列之三(上):ExpandoObject, DynamicObject, DynamicMetaObject
http://www.cnblogs.com/LoveJenny/archive/2011/07/05/2098578.html ExpandoObject:表示一个对象,该对象包含可在运行时动态添加 ...
- Fun with dynamicobject dynamic and the settings table
What came before In my previous post I discussed ways of making the settings table using Generics to ...
- MVC 无法将带 [] 的索引应用于“System.Dynamic.DynamicObject”类型的表达式
无法将带 [] 的索引应用于“System.Dynamic.DynamicObject”类型的表达式 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代 ...
- 当类型为dynamic的视图模型遭遇匿名对象
当年在ASP.NET MVC 1.0时代我提到,在开发时最好将视图的Model定制为强类型的,这样可以充分利用静态检查功能进行排错.不过有人指出,这么做虽然易于静态检查,但是定义强类型的Model类型 ...
- 理解C# 4 dynamic(4) – 让人惊艳的Clay
Clay非常类似于ExpandoObject, 可以看做是ExpandoObject的加强版. 它们能够让我们在不需要定义类的情况下,就构建出我们想要的对象.Clay和ExpandoObject相比, ...
- 不一样的dynamic解析json 万能方法
写过javascript的人都知道js解析json 1:(JSON) 字符串转换为对象. var str = '{"name":"lsw","hobb ...
随机推荐
- HDU 1233 还是畅通工程(最小生成树,prim)
题意:中文题目 思路:prim实现,因为有n*(n-1)/2条边,已经是饱和的边了,prim比较合适. (1)将点1置为浏览过,点1可以到达其他每个点,所以用low[i]数组记录下目前到达i点的最小长 ...
- MYSQL自动备份策略的选择
目前流行几种备份方式: 1.逻辑备份:使用mysql自带的mysqldump工具进行备份.备份成sql文件形式.优点:最大好处是能够与正在运行的mysql自动协同工作,在运行期间可以确保备份是当时的点 ...
- Android启动activity的4种模式(standard、singleTop、singleTask、singleINstance)
在AndroidManifest.xml中配置activity时,android:launchMode属性会指定启动activity的模式,有四种: standard singleTop single ...
- MOSS 2010:Visual Studio 2010开发体验(14)——列表开发之事件接收器
转:http://boke.25k5.com/kan141919.html 通过前面几篇,我们已经完成了内容类型,列表定义,列表实例g 8h"@的开发.本篇继续讲解列表中的一个重要环节- ...
- 我的ECshop二次开发从零开始
我是一个EC新手,EC就算做再多的模板,肯定也满足不了我们的需要,更何况各行有各行的门道,EC统一做出来的模板也不一定合适于我们这个行业用,因此,只有我们真正掌握了自己做模板,修改模板的功夫,才能真正 ...
- 【转】让apache支持中文路径或者中文文件
本帖最后由 狂人阿川 于 2013-4-12 19:13 编辑 今天在给一美国VPS客户调试他的程序的时候.发现他的网站有中文名称.貌似apache无法认识中文路径,火狐下面能下载他的文件,IE下面不 ...
- 字符集编码Unicode ,gb2312 cp936
这是一篇程序员写给程序员的趣味读物.所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级.整理这篇文章的动机是两个问题: 问题一:使用Windows记事本的“另存为” ...
- useful-scripts
最近在github看到关于一些比较好的java相关脚本.vcs脚本.shell脚本.怕以后忘记了,在此做个备注. 原链接为:https://github.com/oldratlee/useful-sc ...
- HDU5727 Necklace
http://acm.hdu.edu.cn/showproblem.php?pid=5727 题意:n个珠子,每个珠子有阴阳两种属性,且阴的一定和阳的紧邻,排成一个环:m行,每行两个数,表示阳性x珠子 ...
- Windows Azure 不能ping通的解决方案
Windows Azure 不能ping通如何解决? 为了避免Ping Flood攻击,Windows Azure不开放对外ICMP通讯协定,所以使用ping命令我们是无法ping通的.在微软资料中心 ...