无法访问或找到对 System.Xml.Linq.LineInfoAnnotation 的引用。为什么是这样?
Cannot access or find reference to System.Xml.Linq.LineInfoAnnotation. Why is this?
我有一个应用程序,它接受 XML 文档并按某些属性对其进行排序。我有与 XML 文档的每一行相关的信息,我想将其包含在已排序的文档中。为了做到这一点,
加载文件时,我确保使用 XDocument.Load(file, LoadOptions.SetLineInfo) 加载行信息。
然后我递归地遍历每个 XElement 并获取它的行信息。当我 运行 应用程序时,我注意到每个 XElement 都有两个注释,
- 类型之一 System.Xml.Linq.LineInfoAnnotation
- 和 System.Xml.Linq.LineInfoEndElementAnnotation.
类型之一
它们包含我需要的信息,但在私有字段中。
我找不到关于这些 class 的任何信息,我无法实例化它们,它们不会出现在 System.Xml.Linq[=38 下的对象浏览器中=].然而它们存在,我可以 运行 "GetType()" 在它们上并获得有关 class 的信息。
如果它们存在,为什么它们不在 MSDN 参考中,为什么我不能实例化它们或扩展它们?为什么我在对象浏览器中找不到它们?
P.S. 我的解决方法是使用反射来获取每个元素中包含的信息。但是我还是不能通过一个class名称来告诉方法它是什么类型,我必须将对象从XElement.Annotations(typeof(object))中隔离出来,然后运行GetType () 在上面。我在下面说明了这一点。
public object GetInstanceField(Type type, object instance, string fieldName)
{
//reflective method that gets value of private field
}
XElement xEl = existingXElement; //existingXElement is passed in
var annotations = xEl.Annotations(typeof(object)); //contains two objects, start and end LineInfoAnnotation
var start = annotations.First();
var end = annotations.Last();
var startLineNumber = GetInstanceField(start.GetType(), start, lineNumber); //lineNumber is private field I'm trying to access.
var endLineNumber = GetInstanceField(end.GetType(), end, lineNumber);
此代码有效,但同样,我不能只告诉方法 "typeof(LineInfoAnnotation)",而是必须对现有对象执行 GetType。我无法理解这一点。
那些 类 是私有的 - 一个实现细节,如果你愿意的话。
所有 XObject(元素、属性)都实现了 IXmlLineInfo 接口 - 但它们显式实现了接口,因此您必须执行转换才能访问属性。
获得 IXmlLineInfo 后,您可以使用属性 LineNumber and LinePosition。
var data =
@"<example>
<someElement
someAttribute=""val"">
</someElement></example>
";
var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(data)), LoadOptions.SetLineInfo);
foreach(var element in doc.Descendants()) {
var elLineInfo = element as IXmlLineInfo;
Console.Out.WriteLine(
$"Element '{element.Name}' at {elLineInfo.LineNumber}:{elLineInfo.LinePosition}");
foreach(var attr in element.Attributes()) {
var attrLineInfo = attr as IXmlLineInfo;
Console.Out.WriteLine(
$"Attribute '{attr.Name}' at {attrLineInfo.LineNumber}:{attrLineInfo.LinePosition}");
}
}
输出:
Element 'example' at 1:2
Element 'someElement' at 2:2
Attribute 'someAttribute' at 3:3
要获取 EndElement 信息,您必须使用普通的旧 XML reader,因为 XObject api 不会公开有关元素结束位置的任何信息。
using(var reader = doc.CreateReader()) {
while(reader.Read()) {
var lineInfo = reader as IXmlLineInfo;
Console.Out.WriteLine($"{reader.NodeType} {reader.Name} at {lineInfo.LineNumber}:{lineInfo.LinePosition}");
if(reader.NodeType == XmlNodeType.Element && reader.HasAttributes) {
while(reader.MoveToNextAttribute()) {
Console.Out.WriteLine($"{reader.NodeType} {reader.Name} at {lineInfo.LineNumber}:{lineInfo.LinePosition}");
}
}
}
}
输出:
Element example at 1:2
Element someElement at 2:2
Attribute someAttribute at 3:3
EndElement someElement at 5:5
EndElement example at 5:19
我有一个应用程序,它接受 XML 文档并按某些属性对其进行排序。我有与 XML 文档的每一行相关的信息,我想将其包含在已排序的文档中。为了做到这一点,
加载文件时,我确保使用 XDocument.Load(file, LoadOptions.SetLineInfo) 加载行信息。
然后我递归地遍历每个 XElement 并获取它的行信息。当我 运行 应用程序时,我注意到每个 XElement 都有两个注释,
- 类型之一 System.Xml.Linq.LineInfoAnnotation
- 和 System.Xml.Linq.LineInfoEndElementAnnotation. 类型之一
它们包含我需要的信息,但在私有字段中。
我找不到关于这些 class 的任何信息,我无法实例化它们,它们不会出现在 System.Xml.Linq[=38 下的对象浏览器中=].然而它们存在,我可以 运行 "GetType()" 在它们上并获得有关 class 的信息。
如果它们存在,为什么它们不在 MSDN 参考中,为什么我不能实例化它们或扩展它们?为什么我在对象浏览器中找不到它们?
P.S. 我的解决方法是使用反射来获取每个元素中包含的信息。但是我还是不能通过一个class名称来告诉方法它是什么类型,我必须将对象从XElement.Annotations(typeof(object))中隔离出来,然后运行GetType () 在上面。我在下面说明了这一点。
public object GetInstanceField(Type type, object instance, string fieldName)
{
//reflective method that gets value of private field
}
XElement xEl = existingXElement; //existingXElement is passed in
var annotations = xEl.Annotations(typeof(object)); //contains two objects, start and end LineInfoAnnotation
var start = annotations.First();
var end = annotations.Last();
var startLineNumber = GetInstanceField(start.GetType(), start, lineNumber); //lineNumber is private field I'm trying to access.
var endLineNumber = GetInstanceField(end.GetType(), end, lineNumber);
此代码有效,但同样,我不能只告诉方法 "typeof(LineInfoAnnotation)",而是必须对现有对象执行 GetType。我无法理解这一点。
那些 类 是私有的 - 一个实现细节,如果你愿意的话。
所有 XObject(元素、属性)都实现了 IXmlLineInfo 接口 - 但它们显式实现了接口,因此您必须执行转换才能访问属性。
获得 IXmlLineInfo 后,您可以使用属性 LineNumber and LinePosition。
var data =
@"<example>
<someElement
someAttribute=""val"">
</someElement></example>
";
var doc = XDocument.Load(new MemoryStream(Encoding.UTF8.GetBytes(data)), LoadOptions.SetLineInfo);
foreach(var element in doc.Descendants()) {
var elLineInfo = element as IXmlLineInfo;
Console.Out.WriteLine(
$"Element '{element.Name}' at {elLineInfo.LineNumber}:{elLineInfo.LinePosition}");
foreach(var attr in element.Attributes()) {
var attrLineInfo = attr as IXmlLineInfo;
Console.Out.WriteLine(
$"Attribute '{attr.Name}' at {attrLineInfo.LineNumber}:{attrLineInfo.LinePosition}");
}
}
输出:
Element 'example' at 1:2
Element 'someElement' at 2:2
Attribute 'someAttribute' at 3:3
要获取 EndElement 信息,您必须使用普通的旧 XML reader,因为 XObject api 不会公开有关元素结束位置的任何信息。
using(var reader = doc.CreateReader()) {
while(reader.Read()) {
var lineInfo = reader as IXmlLineInfo;
Console.Out.WriteLine($"{reader.NodeType} {reader.Name} at {lineInfo.LineNumber}:{lineInfo.LinePosition}");
if(reader.NodeType == XmlNodeType.Element && reader.HasAttributes) {
while(reader.MoveToNextAttribute()) {
Console.Out.WriteLine($"{reader.NodeType} {reader.Name} at {lineInfo.LineNumber}:{lineInfo.LinePosition}");
}
}
}
}
输出:
Element example at 1:2
Element someElement at 2:2
Attribute someAttribute at 3:3
EndElement someElement at 5:5
EndElement example at 5:19