Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XmlReader最佳实践_C#_.net 2.0_Xmlreader - Fatal编程技术网

C# XmlReader最佳实践

C# XmlReader最佳实践,c#,.net-2.0,xmlreader,C#,.net 2.0,Xmlreader,我已经很好地阅读了MSDN和与StackOverflow相关的XmlReader问题,还没有遇到一个像样的“最佳实践”示例 我尝试过各种组合,每种组合似乎都有缺点,但我能想到的最好组合如下: XML: <properties> <actions:name>start</actions:name> <actions:value type="System.DateTime">06/08/2011 01:26:49</actions:val

我已经很好地阅读了MSDN和与StackOverflow相关的XmlReader问题,还没有遇到一个像样的“最佳实践”示例

我尝试过各种组合,每种组合似乎都有缺点,但我能想到的最好组合如下:

XML:

<properties>
  <actions:name>start</actions:name>
  <actions:value type="System.DateTime">06/08/2011 01:26:49</actions:value>
</properties>
这是从.ReadSubTree()调用传递到我的类中的,每个类都读取自己的信息。我宁愿它不依赖于它是在一个特定的顺序

在此之前,我确实尝试了几种变体

1)
while(reader.Read())
这是从各种示例中提取的,但发现当元素1的
.ReadContent*()
将其保留在元素2的开头时,它“遗漏”了一些元素,
.Read
将其读到元素3

2) 删除
.Read()
导致它在我读取第一个元素后卡住

3) 其他几个我长期以来一直认为是“失败的”

就我所见,我确定的代码似乎是最容易接受和最稳定的,但有什么明显的遗漏吗


(注意c#2.0标记,因此LINQ/XNode/XElement不是选项)

一种方法是使用自定义XmlReader。XmlReader是抽象的,XmlReaders可以链接起来,从而提供了一种强大的机制来在阅读器中执行特定于域的处理

例如:

关于XmlWrappingReader

下面是如何实现它的示例(请参见内联注释):

//
///根据Xml结构的复杂性,这里可能需要一个复杂的状态机。
///这样的读取器很好地将Xml的结构与依赖于Xml中数据的业务逻辑分离开来。
/// 
公共类CustomXmlReader:XmlWrappingReader
{
公共自定义XmlReader(XmlReader XmlReader)
:base(XmlReader.Create(XmlReader,XmlReader.Settings))
{
}
公共覆盖bool Read()
{
var b=base.Read();
如果(!b)
返回false;
_myEnum=myEnum.None;
如果(“name.”等于(this.name))
{
_myEnum=myEnum.Name;
//用于读取整个元素并设置枚举、名称和与域相关的任何其他属性的自定义逻辑
//使用base.Read()直到您读取了Xml的完整“逻辑”块。“逻辑”块可以不仅仅是一个元素。
}
如果(“值”。等于(此值))
{
_myEnum=Xml.myEnum.Value;
//用于读取整个元素并设置枚举、值和与域相关的任何其他属性的自定义逻辑
//使用base.Read()直到您读取了Xml的完整“逻辑”块。“逻辑”块可以不仅仅是一个元素。
}
返回true;
}
//这些属性可能返回一些特定于域的值
#区域域特定的读卡器属性。
私有髓鞘;
公共髓鞘
{
获取{return}
}
#端区
}
公共枚举髓鞘
{
名称
价值
没有一个
}
公共类MyBusinessAppClass
{
公共无效DoSomething(XmlReader PassedReader)
{
var myReader=新的CustomXmlReader(passedReader);
while(myReader.Read())
{
开关(myReader.MyEnum)
{
case MyEnum.Name:
//在这里做点什么;
打破
case MyEnum.Value:
//在这里做点什么;
打破
}
}
}
}

警告一句:对于您在这里展示的一些简单的Xml处理来说,这可能过于工程化了。除非有两个以上的元素需要自定义处理,否则不建议使用这种方法。

一种方法是使用自定义XmlReader。XmlReader是抽象的,XmlReaders可以链接起来,从而提供了一种强大的机制来在阅读器中执行特定于域的处理

例如:

关于XmlWrappingReader

下面是如何实现它的示例(请参见内联注释):

//
///根据Xml结构的复杂性,这里可能需要一个复杂的状态机。
///这样的读取器很好地将Xml的结构与依赖于Xml中数据的业务逻辑分离开来。
/// 
公共类CustomXmlReader:XmlWrappingReader
{
公共自定义XmlReader(XmlReader XmlReader)
:base(XmlReader.Create(XmlReader,XmlReader.Settings))
{
}
公共覆盖bool Read()
{
var b=base.Read();
如果(!b)
返回false;
_myEnum=myEnum.None;
如果(“name.”等于(this.name))
{
_myEnum=myEnum.Name;
//用于读取整个元素并设置枚举、名称和与域相关的任何其他属性的自定义逻辑
//使用base.Read()直到您读取了Xml的完整“逻辑”块。“逻辑”块可以不仅仅是一个元素。
}
如果(“值”。等于(此值))
{
_myEnum=Xml.myEnum.Value;
//用于读取整个元素并设置枚举、值和与域相关的任何其他属性的自定义逻辑
//使用base.Read()直到您读取了Xml的完整“逻辑”块。“逻辑”块可以不仅仅是一个元素。
}
返回true;
}
//这些属性可能返回一些特定于域的值
#区域域特定的读卡器属性。
私有髓鞘;
公共髓鞘
{
获取{return}
}
#端区
}
公共枚举髓鞘
{
名称
价值
没有一个
}
公共类MyBusinessAppClass
{
公共无效DoSomething(XmlReader PassedReader)
{
var myReader=新的CustomXmlReader(passedReader);
while(myReader.Read())
{
开关(myReader.MyEnum)
{
case MyEnum.Name:
//在这里做点什么;
打破
// Reads past the initial/root element
reader.ReadStartElement();

// Check we haven't hit the end
while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
    if (reader.IsStartElement("name", NamespaceUri)) {
        // Read the name element
        this.name = reader.ReadElementContentAsString();
    } else if (reader.IsStartElement("value", NamespaceUri)) {
        // Read the value element
        string valueTypeName = reader["type"] ?? typeof(string).Name;
        Type valueType = Type.GetType(valueTypeName);
        string valueString = reader.ReadElementContentAsString();
        // Other stuff here that doesn;t matter to the XML parsing
    } else {
        // We can't do anything with this node so skip over it
        reader.Read();
    }
}
/// <summary>
/// Depending on the complexity of the Xml structure, a complex statemachine could be required here.
/// Such a reader nicely separates the structure of the Xml from the business logic dependent on the data in the Xml. 
/// </summary>
public class CustomXmlReader: XmlWrappingReader
{
    public CustomXmlReader(XmlReader xmlReader)
        :base(XmlReader.Create(xmlReader, xmlReader.Settings))
    {

    }

    public override bool Read()
    {
        var b = base.Read();
        if (!b)
            return false;
        _myEnum = MyEnum.None;
        if("name".Equals(this.Name))
        {
            _myEnum = MyEnum.Name;
            //custom logic to read the entire element and set the enum, name and any other properties relevant to your domain
            //Use base.Read() until you've read the complete "logical" chunk of Xml. The "logical" chunk could be more than a element.
        }
        if("value".Equals(this.Value))
        {
            _myEnum = Xml.MyEnum.Value;
            //custom logic to read the entire element and set the enum, value and and any other properties relevant to your domain
            //Use base.Read() until you've read the complete "logical" chunk of Xml. The "logical" chunk could be more than a element.
        }
        return true;
    }
    //These properties could return some domain specific values
    #region domain specific reader properties. 
    private MyEnum _myEnum;
    public MyEnum MyEnum
    {
        get { return _myEnum; }
    }

    #endregion
}

public enum MyEnum
{
    Name,
    Value,
    None
}

public class MyBusinessAppClass
{
    public void DoSomething(XmlReader passedInReader)
    {

        var myReader = new CustomXmlReader(passedInReader);
         while(myReader.Read())
         {
             switch(myReader.MyEnum)
             {
                 case MyEnum.Name:
                     //Do something here;
                     break;
                 case MyEnum.Value:
                     //Do something here;
                     break;

             }
         }
    }
}