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>

ただし、2 回目の実行で同じファイルをデシリアライズすると、ファイルをロードしようとするとエラーが発生します xs.Deserialize(fs) as TaskServerSettings

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

私はすでに静的メソッドを回避しようとし、親+最後の3つのメソッドnewを削除しようとしたのと同様に試みました。IEqualityComparer成功せずに。

このエラーの原因は何ですか?

4

1 に答える 1

3

このステートメントを実行すると、次のようになります。

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

ストリームの読み取りを開始します。そのため、後で呼び出すDeserializeと、ストリームが開始されていないため、逆シリアル化は失敗します。設定してストリームを巻き戻す必要がありますfs.Position = 0

于 2013-03-19T13:42:41.813 に答える