簡體   English   中英

C#XMLSerializer和屬性序列化序列

[英]C# XMLSerializer and sequence of attribute serialization

我對XML反序列化有問題。 好吧,假設我的課有三個屬性:

public class Order
{
    private string name;
    [XmlAttribute("Name")]
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            if (name != value)
            {
                name = value;
            }
        }
    }

    private string tid;
    [XmlAttribute("TID")]
    public string TID
    {
        get
        {
            return tid;
        }
        set
        {
            if (tid != value)
            {
                tid = value;
            }
        }
    }


    private Command command;
    [XmlAttribute("Command")]
    public string Command
    {
        get
        {
            return command.Name;
        }
        set
        {
            command = new Command(TID, Name, value);
        }
    }

    public Order()
    {

    }
}

如您所見,我需要在反序列化Command屬性上創建一個帶有參數構造函數的Command對象,但是對此我需要TID和Name屬性。 我需要確保這些字段不為空。 正如我觀察到的,XmlSerializer根據用戶編寫序列的順序反序列化屬性。 例如:

<Order Command="SetPlus" TID="W403" Name="SomeName" />

在這種情況下,首先序列化的將是Command屬性。 但是我還沒有TID和Name屬性! 我不能相信用戶他會按正確的順序傳遞屬性,例如:

<Order TID="W403" Name="SomeName" Command="SetPlus" />

好吧,我需要一些事件或可以反序列化完成的東西,或者我需要確保XmlSerializer將按我想要的順序反序列化屬性。 我發現的唯一是:

[XmlElement(Order = 1)]

要么

[XmlElementAttribute(Order = 1)]

但這不適用於XmlAttribute。

有什么辦法做到這一點? 希望我能清楚地解釋我的問題。

如果您的Command僅取決於TIDName為什么還要序列化它? 這只是多余的信息。

您應該在Command屬性上使用[XmlIgnore]屬性。 之后,您可以為Command屬性實現一種惰性加載方法。

順便說一句:您的代碼仍然是錯誤的。 Command屬性的set部分上,甚至不使用用戶傳入的值。如果這樣做,會更好:

private Command command;
[XmlIgnore]
public string Command
{
    get
    {
      if (command == null)
      {
        command = new Command(TID, Name));
      }
      return command.Name;
    }
}

編輯:

好的,在您更改帖子並實際使用Command屬性設置器的值之后,解決方案會有些棘手,並且有多種方法。

我可能會做什么:

  • 向您的類中添加另一個名為CommandName屬性,這只是一個簡單的字符串屬性(帶有getter),還向該屬性添加XmlAttribute
  • [XmlIgnore]添加到您的Command屬性,並從上方獲取我的代碼(延遲初始化),使用新的CommandName屬性( new Command(TID, Name, CommandName) )返回命令

我個人甚至會在CommandName屬性中添加一個setter,並讓Command屬性實際上返回Command而不是string 在我看來,這將使代碼更整潔,更易讀。

為了澄清,這是我的班級樣子:

public class Order
{
    //todo: if Name, TID or CommandName changes you'd have to initialize a new Command objects with the new values

    [XmlAttribute("Name")]
    public string Name {get;set;}

    [XmlAttribute("TID")]
    public string TID {get;set;}

    [XmlAttribute("CommandName")]
    public string CommandName {get;set;}

    private Command command;
    [XmlIgnore]
    public Command Command
    {
      get
      {
        return command ?? (command = new Command(TID, Name, CommandName));
      }
    }
    public Order()
    {

    }
}

您可以在設置器中添加一些邏輯,以便在調用所有設置器后,按如下所示創建命令

public class Order
{
    private string name;
    [XmlAttribute("Name")]
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            if (name != value)
            {
                name = value;
                SetupCommandIfPossible();
            }

        }
    }

    private string tid;
    [XmlAttribute("TID")]
    public string TID
    {
        get
        {
            return tid;
        }
        set
        {
            if (tid != value)
            {
                tid = value;
                SetupCommandIfPossible();
            }
        }
    }


    private Command command;
    [XmlAttribute("Command")]
    public string Command
    {
        get
        {
            return command.Name;
        }
        set
        {
            SetupCommandIfPossible();
        }
    }

    public void SetupCommandIfPossible()
    {
         if (!string.IsNullOrEmpty(tid) && !string.IsNullOrEmpty(name) && command == null)
         {             
            command = new Command(TID, Name);
         }
    }

    public Order()
    {

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM