2013-03-19 104 views
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父+最後的三種方法。沒有成功。

我想知道,這個錯誤是什麼原因?

回答

3

當你執行該語句:

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

它開始讀取數據流。所以當你稍後調用Deserialize時,該流不在開始處,所以反序列化失敗。您需要通過設置倒帶流fs.Position = 0

+0

當!而已。謝謝。 =) – modiX 2013-03-19 13:49:02

相關問題