C#XMLSerializer和属性序列化序列
我对XML反序列化有问题。好吧,假设我的类有三个属性:C#XMLSerializer和属性序列化序列,c#,xml,deserialization,C#,Xml,Deserialization,我对XML反序列化有问题。好吧,假设我的类有三个属性: public class Order { private string name; [XmlAttribute("Name")] public string Name { get { return name; } set { if (name != value)
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()
{
}
}
如您所见,我需要在反序列化命令属性上创建一个带有参数构造函数的对象命令,但我需要TID和Name属性。我需要确保这些字段不为空。正如我所观察到的,XmlSerializer正在根据用户编写属性的顺序对属性进行反序列化。例如:
<Order Command="SetPlus" TID="W403" Name="SomeName" />
或
但它不适用于XmlAttribute
有办法做到这一点吗?希望我能清楚地解释我的问题。您能在setter中添加一些逻辑,以便在调用所有setter后,您可以像这样创建命令吗
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()
{
}
}
如果您的
命令
仅依赖于TID
和名称
为什么还要序列化它?
这只是多余的信息
您应该在命令
属性上使用[XmlIgnore]
属性。
之后,您可以为命令
属性实现一种延迟加载方法
顺便说一下:你的代码是错误的。在命令
属性的集合
部分,您甚至不使用用户传入的值。
如果你这样做会更好:
private Command command;
[XmlIgnore]
public string Command
{
get
{
if (command == null)
{
command = new Command(TID, Name));
}
return command.Name;
}
}
编辑:
好的,在您更改了帖子并实际使用了命令的值之后,解决方案就有点棘手了,而且有多种方法
我可能会做的是:
- 将另一个名为
CommandName
的属性添加到类中,它只是一个简单的字符串属性(带有getter),还可以将和xmltattribute
添加到此属性中
- 将
[XmlIgnore]
添加到您的命令
属性,并从上面获取我的代码(惰性初始化),使用新的命令名
属性返回命令(新命令(TID,Name,CommandName)
)
就我个人而言,我甚至会在CommandName
属性中添加一个setter,让Command
属性实际返回一个Command
,而不是字符串。在我看来,这将使代码更干净,更具可读性
为了澄清,我的课堂是这样的:
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()
{
}
}
您是否对所有公共成员使用Order属性?就此而言,为什么它甚至有一个setter?我猜他说的是反序列化而不是序列化。问题更复杂。我举了一个非常简单的例子来理解它,但忘记了添加“value”,如下所示:command=newcommand(TID,Name,value);刚刚意识到setter的“bug”,我用一个(在我看来)正确的例子更新了我的答案。当然我使用的是value,我只是忘记了将它作为参数添加到构造函数中。对不起,我弄错了。我考虑过这个问题,我希望这是一个更优雅的解决方案(这没什么错,它比基于属性的方法更易于测试
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()
{
}
}
private Command command;
[XmlIgnore]
public string Command
{
get
{
if (command == null)
{
command = new Command(TID, Name));
}
return command.Name;
}
}
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()
{
}
}