I have a problem with XML deserialization. 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. 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. For example:
<Order Command="SetPlus" TID="W403" Name="SomeName" />
In this case, first serialized will be Command attribute. But I don't have TID and Name property yet! 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. The only thing I found is:
[XmlElement(Order = 1)]
or
[XmlElementAttribute(Order = 1)]
But it doesn't work with 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? This is just redundant information.
You should use the [XmlIgnore]
attribute on the Command
property. After that you can implement a kind of lazy load method for your Command
property.
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:
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.
What I'd probably do:
CommandName
to your class, which just is a simple string property (with getter), also add and XmlAttribute
to this property [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)
) Personally I would even add a setter to the CommandName
property and let the Command
property actually return a Command
and not a 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()
{
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.