1

我通过为实例调用自己的静态函数来获得具有某些属性的类的对象。如果存在 XML 文件,则对象会尝试加载它并将其值添加到实例本身。然后它将再次保存 XML,以防 XML 文件中缺少选项。

我创建了一个小型控制台应用程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml;

namespace Test
{
    public class Program
    {
        static void Main(string[] args)
        {
            TaskServerSettings s = TaskServerSettings.LoadNew();
        }
    }

    public class TaskServerSettings : IEqualityComparer
    {
        #region SETTINGS PROPERTIES

        public bool Enabled { get; set; }
        public int CheckInterval { get; set; }

        #endregion

        #region CONSTRUCTORS AND METHODS

        public TaskServerSettings()
        {
            this.init();
        }

        public TaskServerSettings(string settingsFile)
        {
            this.init();
            if (settingsFile != null)
            {
                if (File.Exists(settingsFile))
                {
                    this.Load(settingsFile);
                }
                this.Save(settingsFile);
                }
        }

        private void init()
        {
            this.Enabled = true;
            this.CheckInterval = 5000;
        }

        public void Absorb(TaskServerSettings newSettings)
        {
            this.Enabled = newSettings.Enabled;
            this.CheckInterval = newSettings.CheckInterval;
        }

        public static TaskServerSettings LoadNew(string settingsFile = null)
        {
            if (settingsFile == null)
            {
                settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
            }

            return new TaskServerSettings(settingsFile);
        }

        public bool Load(string settingsFile = null)
        {
            if (settingsFile == null)
            {
                settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
            }

            if (!File.Exists(settingsFile))
            {
                throw new FileNotFoundException("Could not find \"" + settingsFile + "\" to load settings.");
            }

            bool result = false;
            using (FileStream fs = new FileStream(settingsFile, FileMode.Open))
            {
                XmlSerializer xs = new XmlSerializer(this.GetType());
                if (!xs.CanDeserialize(XmlReader.Create(fs)))
                {
                    throw new XmlException("\"" + settingsFile + "\" does not have a valid TaskServerSettings XML structure.");
                }
                //try
                //{            // +- InvalidOperationException - Error in XML document (0,0).
                               // v  The root element is missing.
                    this.Absorb(xs.Deserialize(fs) as TaskServerSettings);
                    result = true;
                //}
                //catch { }
            }

            return result;
        }

        public bool Save(string settingsFile = null)
        {
            if (settingsFile == null)
            {
                settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
            }

            bool result = false;
            using (FileStream fs = new FileStream(settingsFile, FileMode.Create))
            {
                XmlSerializer xs = new XmlSerializer(this.GetType());
                try
                {
                    xs.Serialize(fs, this);
                    result = true;
                }
                catch { }
            }

            return result;
        }

        #endregion

        public bool Equals(TaskServerSettings settingsToCompare)
        {
            if (this.Enabled != settingsToCompare.Enabled ||
                this.CheckInterval != settingsToCompare.CheckInterval)
            {
                return false;
            }
            return true;
        }
        bool IEqualityComparer.Equals(object x, object y)
        {
            return x.Equals(y);
        }
        int IEqualityComparer.GetHashCode(object obj)
        {
            throw new NotSupportedException();
        }
    }
}

在第一次运行时使用其默认属性值编写对象效果很好。XML 文件如下所示:

<?xml version="1.0"?>
<TaskServerSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Enabled>true</Enabled>
  <CheckInterval>5000</CheckInterval>
</TaskServerSettings>

但是,在第二次运行时反序列化同一文件会在尝试将文件加载到 xs.Deserialize(fs) as TaskServerSettings.

InvalidOperationException - Error in XML document (0,0).
The root element is missing.

我已经尝试避免使用静态方法并尝试过new,并且我已经尝试过删除IEqualityComparer父级+最后三个方法。没有成功。

我想知道,这个错误的原因是什么?

4

1 回答 1

3

当您执行此语句时:

if (!xs.CanDeserialize(XmlReader.Create(fs)))

它开始读取流。所以当你Deserialize稍后调用时,流不在开始,所以反序列化失败。您需要通过设置倒带流fs.Position = 0

于 2013-03-19T13:42:41.813 回答