< books >
< book >
< title > Mortal Engines </ title >
< author name ="" Philip Reeve "" />
</ book >
< book >
< title > The Talisman </ title >
< author name ="" Stephen King "" />
< author name ="" Peter Straub "" />
</ book >
</ books >
* This source code was highlighted with Source Code Highlighter .
var element = XElement .Parse(books);
string firstBooksTitle =
element.Element( "book" ).Element( "title" ).Value;
Assert.That(firstBooksTitle, Is.EqualTo( "Mortal Engines" ));
string firstBooksAuthor =
element.Element( "book" ).Element( "author" ). Attribute ( "name" ).Value;
Assert.That(firstBooksAuthor, Is.EqualTo( "Philip Reeve" ));
string secondBooksTitle =
element.Elements().ElementAt(1).Element( "title" ).Value;
Assert.That(secondBooksTitle, Is.EqualTo( "The Talisman" ));
* This source code was highlighted with Source Code Highlighter .
// Dynamic Wrapper XElement
dynamic dynamicElement = // ...
//
string firstBooksTitle = dynamicElement.book.title;
Assert.That(firstBooksTitle, Is.EqualTo( "Mortal Engines" ));
// , ,
string firstBooksAuthor = dynamicElement.book.author[ "name" ];
Assert.That(firstBooksAuthor, Is.EqualTo( "Philip Reeve" ));
// , ,
string secondBooksTitle = dynamicElement.book[1].title;
Assert.That(secondBooksTitle, Is.EqualTo( "The Talisman" ));
* This source code was highlighted with Source Code Highlighter .
/// <summary>
/// " " XElement
/// </summary>
public class DynamicXElementReader : DynamicObject
{
private readonly XElement element;
private DynamicXElementReader( XElement element)
{
this .element = element;
}
public static dynamic CreateInstance( XElement element)
{
Contract.Requires(element != null );
Contract.Ensures(Contract.Result< object >() != null );
return new DynamicXElementReader(element);
}
}
* This source code was highlighted with Source Code Highlighter .
public class DynamicXElementReader : DynamicObject
{
/// <summary>
/// true, .
/// </summary>
/// <remarks>
/// Pure
/// </remarks>
[Pure]
public bool HasParent()
{
return element.Parent != null ;
}
public dynamic this [XName name]
{
get
{
Contract.Requires(name != null );
XAttribute attribute = element. Attribute (name);
if (attribute == null )
throw new InvalidOperationException(
"Attribute not found. Name: " + name.LocalName);
return attribute.AsDynamic();
}
}
public dynamic this [ int idx]
{
get
{
Contract.Requires(idx >= 0, "Index should be greater or equals to 0" );
Contract.Requires(idx == 0 || HasParent(),
"For non-zero index we should have parent element" );
//
if (idx == 0)
return this ;
// "" .
// ,
var parent = element.Parent;
Contract.Assume(parent != null );
XElement subElement = parent.Elements().ElementAt(idx);
// subElement null, ElementAt
// , .
// ,
// Contract.Assume
Contract.Assume(subElement != null );
return CreateInstance(subElement);
}
}
public XElement XElement { get { return element; } }
}
* This source code was highlighted with Source Code Highlighter .
public class DynamicXElementReader : DynamicObject
{
// not used
private XElement element;
public static dynamic CreateInstance( XElement ) { return null ;}
/// <summary>
/// :
/// SomeType variable = dynamicElement;
/// </summary>
public override sealed bool TryConvert(ConvertBinder binder, out object result)
{
// XElement
// xml-
if (binder.ReturnType == typeof ( XElement ))
{
result = element;
return true ;
}
//
//
string underlyingValue = element.Value;
result = Convert .ChangeType(underlyingValue, binder.ReturnType,
CultureInfo.InvariantCulture);
return true ;
}
/// <summary>
///
/// </summary>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string binderName = binder.Name;
Contract.Assume(binderName != null );
// ,
//
XElement subelement = element.Element(binderName);
if (subelement != null )
{
result = CreateInstance(subelement);
return true ;
}
// ,
//
return base .TryGetMember(binder, out result);
}
}
* This source code was highlighted with Source Code Highlighter .
// bookXElement
string firstBooksElement = dynamicElement.book;
Console .WriteLine( "First books element: {0}" , firstBooksElement);
//
string firstBooksTitle = dynamicElement.book.title;
Console .WriteLine( "First books title: {0}" , firstBooksTitle);
// int
int firstBooksPageCount = dynamicElement.book.pages;
Console .WriteLine( "First books page count: {0}" , firstBooksPageCount);
* This source code was highlighted with Source Code Highlighter .
First books element: < book >
< title > Mortal Engines </ title >
< author name ="Philip Reeve" />
< pages > 347 </ pages >
</ book >
First books title: Mortal Engines
First books page count: 347
First books author: Philip Reeve
Second books title: The Talisman
* This source code was highlighted with Source Code Highlighter .
public class DynamicXElementWriter : DynamicObject
{
// ,
/// <summary>
///
/// </summary>
public void SetValue( object value )
{
Contract.Requires( value != null );
element.SetValue( value );
}
/// <summary>
///
/// </summary>
public void SetAttributeValue(XName name, object value )
{
Contract.Requires(name != null );
Contract.Requires( value != null );
element.SetAttributeValue(name, value );
}
/// <summary>
///
/// </summary>
public dynamic this [XName name]
{
get
{
//
}
set
{
//
// XElement.SetAttributeValue,
element.SetAttributeValue(name, value );
}
}
/// <summary>
/// ""
/// </summary>
public dynamic this [ int idx]
{
get
{
//
Contract.Requires(idx >= 0, "Index should be greater or equals to 0" );
Contract.Requires(idx == 0 || HasParent(),
"For non-zero index we should have parent element" );
//
if (idx == 0)
return this ;
// "" .
// ,
var parent = element.Parent;
Contract.Assume(parent != null );
// "" ,
//
XElement subElement = parent.Elements(element.Name).ElementAtOrDefault(idx);
if (subElement == null )
{
XElement sibling = parent.Elements(element.Name).First();
subElement = new XElement (sibling.Name);
parent.Add(subElement);
}
return CreateInstance(subElement);
}
set
{
Contract.Requires(idx >= 0, "Index should be greater or equals to 0" );
Contract.Requires(idx == 0 || HasParent(),
"For non-zero index we should have parent element" );
//
// ,
//
dynamic d = this [idx];
d.SetValue( value );
return ;
}
}
}
* This source code was highlighted with Source Code Highlighter .
/// <summary>
///
/// </summary>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string binderName = binder.Name;
Contract.Assume(binderName != null );
//
XElement subelement = element.Element(binderName);
// ,
//
if (subelement == null )
{
subelement = new XElement (binderName);
element.Add(subelement);
}
result = CreateInstance(subelement);
return true ;
}
/// <summary>
///
/// </summary>
public override bool TrySetMember(SetMemberBinder binder, object value )
{
Contract.Assume(binder != null );
Contract.Assume(! string .IsNullOrEmpty(binder.Name));
Contract.Assume( value != null );
string binderName = binder.Name;
// ,
// , ;
// XElement.SetElementValue,
//
if (binderName == element.Name)
element.SetValue( value );
else
element.SetElementValue(binderName, value );
return true ;
}
* This source code was highlighted with Source Code Highlighter .
Source: https://habr.com/ru/post/119036/