我有两个类,一个继承另一个类 - 基类是DataContract,子类是Serializable。我想将属性从子类移动到基类,但在移动之后我得到例外,说在反序列化子类时没有找到BackingProperty。如何正确地将该属性移动到基类?
答案 0 :(得分:0)
您是否使用KnownType属性修饰了基类?
[KnownType(typeof(SuperClass))]
[DataContract]
public class BaseClass
{
...
}
答案 1 :(得分:0)
这是因为Serializable标记类和DataContract的序列化有点不同。
这是我用于样本的序列化器:
var ser = new DataContractSerializer(typeof(BaseClass), new List<Type>() { typeof(ChildClass) });
您可以比较:
[DataContract]
public class BaseClass
{
[DataMember]
public string Name { get; set; }
}
[Serializable]
public class ChildClass: BaseClass
{
public string SecondName { get; set; }
public int Age { get;set; }
}
该类的Xml(使用DataContractSerializer,这是WCF的标准):
<BaseClass i:type="ChildClass" xmlns="http://schemas.datacontract.org/2004/07/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>Ivan</Name>
<_x003C_Age_x003E_k__BackingField>1</_x003C_Age_x003E_k__BackingField>
<_x003C_SecondName_x003E_k__BackingField>Petrov</_x003C_SecondName_x003E_k__BackingField>
</BaseClass>
但是当您将属性移动到基类时,标记为广告DataContract:
[DataContract]
public class BaseClass
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string SecondName { get; set; }
}
[Serializable]
public class ChildClass: BaseClass
{
public int Age { get;set; }
}
以下是该案例的xml:
<BaseClass i:type="ChildClass" xmlns="http://schemas.datacontract.org/2004/07/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>Ivan</Name>
<SecondName>Petrov</SecondName>
<_x003C_Age_x003E_k__BackingField>1</_x003C_Age_x003E_k__BackingField>
</BaseClass> <BaseClass i:type="ChildClass" xmlns="http://schemas.datacontract.org/2004/07/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>Ivan</Name>
<SecondName>Petrov</SecondName>
<_x003C_Age_x003E_k__BackingField>1</_x003C_Age_x003E_k__BackingField>
</BaseClass>
因此,你在Xml中有不同的元素名称(SecondName vs _x003C_SecondName_x003E_k__BackingField),这两个xml真的不同。
最好在解决方案中使用通用方法,标记所有内容或Serializable或DataContract。我建议使用DataContract。
编辑1:
当然,您可以尝试使用属性命名来制作技巧:
[DataMember(Name = @"_x003C_SecondName_x003E_k__BackingField", IsRequired = true)]
public string SecondName { get; set; }
结果中XML将完全相同。您还可以尝试为Serializable对象而不是属性公开feild:
[Serializable]
public class ChildClass : BaseClass
{
public string SecondName;// { get; set; }
public int Age; //{get;set;}
}
xml将是:
<BaseClass i:type="ChildClass" xmlns="http://schemas.datacontract.org/2004/07/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>Ivan</Name>
<Age>1</Age>
<SecondName>Petrov</SecondName>
</BaseClass>
但是,不幸的是,如果将属性从ChildClass移动到BaseClass,属性的顺序将会改变。但DataContractSerializer始终在反序列化期间强制执行元素的顺序,因此不会对所有字段进行反序列化。但您可以切换到服务中使用XmlSerializer,它支持无序反序列化。
最后:使用DataContract标记所有数据合同
即使您使用DataContract标记您的类,DataMember:
[DataContract]
public class BaseClass
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string SecondName { get; set; }
}
[DataContract]
public class ChildClass : BaseClass
{
//[DataMember]
//public string SecondName { get; set; }
[DataMember]
public int Age {get;set;}
}
然后将属性从ChildClass移动到BaseClass,它仍然无效。您的属性将为null(或默认值),因为订单已更改:(