本文转载: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
- {
-
-
-
-
-
-
-
-
- class Program
- {
- static void Main(string[] args)
- {
-
-
-
- dynamic person = new DynamicDictionary();
-
-
-
- person.FirstName = "Ellen";
- person.LastName = "Adams";
-
-
-
- Console.WriteLine(person.FirstName + " " + person.lastname);
-
- Console.WriteLine("NUmber of dynamic properties" + person.Count);
-
-
- try
- {
-
-
-
- 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
- {
-
-
-
-
-
-
-
-
-
- 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;
- }
-
-
-
-
- public override bool TryConvert(ConvertBinder binder, out object result)
- {
- if (binder.Type == typeof(string))
- {
- result = node.Value;
- return true;
- }
- else
- {
- result = null;
- return false;
- }
- }
-
-
-
-
- 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)
- {
-
- DynamicXMLNodeMain.DynamicXMLNodeCreateReturnValidDynamixXMLNode();
- DynamicXMLNodeMain.DynamicXMLNodeConvertToStringReturnXElementValue();
- DynamicXMLNodeMain.DynamicXMLNodeTryInvokeMemberCallXElementMethods();
-
- }