无法访问或找到对 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 都有两个注释,

它们包含我需要的信息,但在私有字段中。

我找不到关于这些 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