Created
September 25, 2017 20:51
-
-
Save melvinstubbe/477e33d8c026e85a1077eaceaef934a1 to your computer and use it in GitHub Desktop.
Example of a class that parses an existing XML object into a C# 'dynamic' object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Dynamic; | |
using System.Linq; | |
using System.Xml.Linq; | |
namespace DynamicExample | |
{ | |
/// <summary> | |
/// Parses an existing XML object into a C# 'dynamic' object. | |
/// </summary> | |
/// <seealso cref="System.Dynamic.DynamicObject" /> | |
public class DynamicXmlParser : DynamicObject | |
{ | |
private readonly XElement root; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="DynamicXmlParser"/> class. | |
/// </summary> | |
/// <param name="root">The root.</param> | |
public DynamicXmlParser(XElement root) | |
{ | |
this.root = root; | |
} | |
/// <summary> | |
/// Provides the implementation for operations that get member values. | |
/// Specifies dynamic behavior for operations such as getting a value for a property. | |
/// </summary> | |
/// <param name="binder"> | |
/// Provides information about the object that called the dynamic operation. | |
/// The binder.Name property provides the name of the member on which the dynamic operation is performed. | |
/// For example, for the Console.WriteLine(sampleObject.SampleProperty) statement, | |
/// where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, | |
/// binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive. | |
/// </param> | |
/// <param name="result"> | |
/// The result of the get operation. For example, if the method is called for a property, you can assign the property value to <paramref name="result" />. | |
/// </param> | |
/// <returns> | |
/// true if the operation is successful; otherwise, false. | |
/// If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.) | |
/// </returns> | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
result = null; | |
var attribute = root.Attributes().FirstOrDefault(att => att.Name.LocalName.Equals(binder.Name)); | |
if (attribute != null) | |
{ | |
result = attribute.Value; | |
return true; | |
} | |
var nodesList = root.Elements().Where(el => el.Name.LocalName.Equals(binder.Name)); | |
if (nodesList.Count() > 1) | |
{ | |
result = nodesList.Select(n => n.HasElements ? (object)new DynamicXmlParser(n) : n.Value).ToList(); | |
return true; | |
} | |
else | |
{ | |
var node = nodesList.FirstOrDefault(); | |
if (node != null) | |
{ | |
result = node.HasElements ? (object)new DynamicXmlParser(node) : node.Value; | |
return true; | |
} | |
} | |
return true; | |
} | |
/// <summary> | |
/// Provides implementation for type conversion operations. Classes derived from the <see cref="T:System.Dynamic.DynamicObject" /> class can | |
/// override this method to specify dynamic behavior for operations that convert an object from one type to another. | |
/// </summary> | |
/// <param name="binder"> | |
/// Provides information about the conversion operation. The binder.Type property provides the type to which the object must be converted. | |
/// For example, for the statement (String)sampleObject, binder.Type returns the <see cref="T:System.String" /> type. | |
/// The binder.Explicit property provides information about the kind of conversion that occurs. | |
/// It returns true for explicit conversion and false for implicit conversion. | |
/// </param> | |
/// <param name="result">The result of the type conversion operation.</param> | |
/// <returns> | |
/// true if the operation is successful; otherwise, false. | |
/// If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.) | |
/// </returns> | |
public override bool TryConvert(ConvertBinder binder, out object result) | |
{ | |
if (binder.Type == typeof(string) || binder.Type == typeof(String)) | |
{ | |
result = root.ToString(); | |
return true; | |
} | |
return base.TryConvert(binder, out result); | |
} | |
/// <summary> | |
/// Returns a <see cref="System.String" /> that represents this instance. | |
/// </summary> | |
/// <returns> | |
/// A <see cref="System.String" /> that represents this instance. | |
/// </returns> | |
public override string ToString() | |
{ | |
return root.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment