简体   繁体   English

C#XMLSerializer和属性序列化序列

[英]C# XMLSerializer and sequence of attribute serialization

I have a problem with XML deserialization. 我对XML反序列化有问题。 Well, lets suppose that my class have three properties: 好吧,假设我的课有三个属性:

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()
    {

    }
}

As you can see, I need to create an object Command with parameter constructor on deserialize Command property - but I need TID and Name attribute to this. 如您所见,我需要在反序列化Command属性上创建一个带有参数构造函数的Command对象,但是对此我需要TID和Name属性。 I need to be sure that these fields are not null. 我需要确保这些字段不为空。 As I observed, XmlSerializer is deserializing attributes according to sequence how user write it. 正如我观察到的,XmlSerializer根据用户编写序列的顺序反序列化属性。 For example: 例如:

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

In this case, first serialized will be Command attribute. 在这种情况下,首先序列化的将是Command属性。 But I don't have TID and Name property yet! 但是我还没有TID和Name属性! I can't trust user that he will pass attributes in correct sequence like: 我不能相信用户他会按正确的顺序传递属性,例如:

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

Well, I need some event or something I can call on deserialize finish OR I need to be sure that XmlSerializer will deserialize attributes in sequence like I want. 好吧,我需要一些事件或可以反序列化完成的东西,或者我需要确保XmlSerializer将按我想要的顺序反序列化属性。 The only thing I found is: 我发现的唯一是:

[XmlElement(Order = 1)]

or 要么

[XmlElementAttribute(Order = 1)]

But it doesn't work with XmlAttribute. 但这不适用于XmlAttribute。

Is some way to do this? 有什么办法做到这一点? Hope I explained my problem clearly. 希望我能清楚地解释我的问题。

If your Command only depends on the TID and the Name why do you even serialize it? 如果您的Command仅取决于TIDName为什么还要序列化它? This is just redundant information. 这只是多余的信息。

You should use the [XmlIgnore] attribute on the Command property. 您应该在Command属性上使用[XmlIgnore]属性。 After that you can implement a kind of lazy load method for your Command property. 之后,您可以为Command属性实现一种惰性加载方法。

By the way: Your code is wrong anyway. 顺便说一句:您的代码仍然是错误的。 On the set part of your Command property, you don't even use the value the user passed in. It would be better if you'd do it like this: Command属性的set部分上,甚至不使用用户传入的值。如果这样做,会更好:

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

edit: 编辑:

ok after you changed your post and actually use the value of the Command property setter, the solution is a little trickier and there are multiple ways. 好的,在您更改帖子并实际使用Command属性设置器的值之后,解决方案会有些棘手,并且有多种方法。

What I'd probably do: 我可能会做什么:

  • Add another property called CommandName to your class, which just is a simple string property (with getter), also add and XmlAttribute to this property 向您的类中添加另一个名为CommandName属性,这只是一个简单的字符串属性(带有getter),还向该属性添加XmlAttribute
  • Add the [XmlIgnore] to your Command property, and take my code from above (lazy initialization), return the command using the new CommandName property ( new Command(TID, Name, CommandName) ) [XmlIgnore]添加到您的Command属性,并从上方获取我的代码(延迟初始化),使用新的CommandName属性( new Command(TID, Name, CommandName) )返回命令

Personally I would even add a setter to the CommandName property and let the Command property actually return a Command and not a string . 我个人甚至会在CommandName属性中添加一个setter,并让Command属性实际上返回Command而不是string In my opinion this would make the code cleaner and more readable. 在我看来,这将使代码更整洁,更易读。

For clarification, this is how my class would look like: 为了澄清,这是我的班级样子:

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()
    {

    }
}

Can you put some logic in the setters so that when all the setters have been called you then create the command like so 您可以在设置器中添加一些逻辑,以便在调用所有设置器后,按如下所示创建命令

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