我正在尝试使用Fluent接口解析XML,如here所述。
示例很好但是给出了一个我无法修复的编译器错误。
错误位于以下受保护的构造函数中:
protected DynamicXml( IEnumerable<XElement> elements )
{
_elements = new List<XElement>( elements ); // error on this line
}
我在这一行得到的两个编译器错误是:
Argument 1: cannot convert from
'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' to
'System.Xml.Linq.XElement'
和
The best overloaded Add method
'System.Collections.Generic.List<System.Xml.Linq.XElement>.
Add(System.Xml.Linq.XElement)' for the collection initializer
has some invalid arguments
我已复制/粘贴以下完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;
using System.Xml.Linq;
using System.Collections;
namespace FluentXML
{
public class DynamicXml : DynamicObject, IEnumerable
{
private readonly List<XElement> _elements;
public DynamicXml(string text)
{
var doc = XDocument.Parse(text);
_elements = new List<XElement> { doc.Root };
}
protected DynamicXml(XElement element)
{
_elements = new List<XElement> { element };
}
protected DynamicXml(IEnumerable<XElement> iteratorElem)
{
_elements = new List<XElement> { iteratorElem };
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
if (binder.Name == "Value")
result = _elements[0].Value;
else if (binder.Name == "Count")
result = _elements.Count;
else
{
var attr = _elements[0].Attribute(
XName.Get(binder.Name));
if (attr != null)
result = attr;
else
{
var items = _elements.Descendants(
XName.Get(binder.Name));
if (items == null || items.Count() == 0)
return false;
result = new DynamicXml(items);
}
}
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
int ndx = (int)indexes[0];
result = new DynamicXml(_elements[ndx]);
return true;
}
public IEnumerator GetEnumerator()
{
foreach (var element in _elements)
yield return new DynamicXml(element);
}
}
}
namespace FluentXML
{
class Program
{
static void Main(string[] args)
{
string xmlString = FluentXML.Properties.Resources.InputString;
dynamic dx = new DynamicXml(xmlString);
Console.WriteLine("PublicationDate='{0}'", dx.pubdate.Value);
Console.WriteLine("BookCount='{0}'", dx.book.Count);
foreach (dynamic d in dx.book)
{
Console.WriteLine("----- Begin Book -----");
Console.WriteLine("Price='{0}'", d.price.Value);
Console.WriteLine("Title='{0}'", d.title.Value);
Console.WriteLine("AuthorCount='{0}'", d.authors.author.Count);
foreach (dynamic a in d.authors.author)
{
Console.WriteLine(" ---- Begin Author ----");
Console.WriteLine(" EmailAddress='{0}'", a.email.address.Value);
Console.WriteLine(" FirstName='{0}'", a.name.first.Value);
Console.WriteLine(" MiddleName='{0}'", a.name.middle.Value);
Console.WriteLine(" LastName='{0}'", a.name.last.Value);
Console.WriteLine(" ----- End Author -----");
}
Console.WriteLine("------ End Book ------");
}
}
}
}
答案 0 :(得分:3)
protected DynamicXml(IEnumerable<XElement> iteratorElem)
{
_elements = new List<XElement> { iteratorElem };
}
是序列初始化程序。这将创建一个包含一个元素“iteratorElem”的列表,该元素不是XElement类型(如错误所示)。
通话:
protected DynamicXml(IEnumerable<XElement> iteratorElem)
{
_elements = new List<XElement>(iteratorElem);
}
但是,应该可行。你也可以写iteratorElem.ToList()
答案 1 :(得分:3)
您在第一个代码示例中发布的受保护构造函数与您在第二个代码示例中发布的构造函数不同...
这个会奏效!
protected DynamicXml( IEnumerable<XElement> elements )
{
_elements = new List<XElement>( elements ); // error on this line
}
这个不会! :(
protected DynamicXml(IEnumerable<XElement> iteratorElem)
{
_elements = new List<XElement> { iteratorElem };
}
区别在于使用括号与初始化程序块(不确定这是否为技术术语)。带括号的版本将调用泛型List构造函数重载,该重载将通用IEnumerable作为参数。带有大括号的版本将尝试将通用IEnumerable添加为列表中的单个元素。