如何使用数据合同序列化程序序列化没有外部元素的列表?我正在使用.Net 3.5。我有一个包含列表的类,除其他外,我希望序列化,而外部元素不符合相关的XSD:
[DataContract(Name="MyClass")]
public class MyClass
{
...
[DataMember(Name="Parameters")]
public List<Parameter> Parameters;
...
}
[DataContract(Name="Parameter")]
public struct Parameter
{
[DataMember(Name="ValueName")]string ValueName;
[DataMember(Name="Value")]int Value;
public Parameter(string ValueName, int Value)
{
this.ValueName = ValueName;
this.Value = Value;
}
}
以上序列化为(假设列表中只有一个参数):
<MyClass>
<Parameters>
<Parameter>
<ValueName></ValueName>
<Value></Value>
</Parameter>
</Parameters>
</MyClass>
我想将其序列化如下:
<MyClass>
<Parameter>
<ValueName></ValueName>
<Value></Value>
</Parameter>
</MyClass>
使用XmlSerializer我可以通过将[XmlElement]应用于列表来完成此操作:
[XmlElement ("Parameter")]
public List<Parameter> Parameters;
但是我不想使用XmlSerializer
,因为我的类有一些非序列化友好的属性,我希望处理那些使用[OnSerializing]属性系列的属性。
感谢。
答案 0 :(得分:4)
DataContract
序列化程序不允许对结果XML进行这种程度的控制,您必须使用XmlSerializer
来实现此目的。
答案 1 :(得分:2)
使用收集数据合同:
[CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
public class ParameterList : List<Parameter>
{
}
以下是实际代码:
public class TestSerialize
{
[DataContract(Name = "Parameter")]
public struct Parameter
{
[DataMember(Name = "ValueName")] string ValueName;
[DataMember(Name = "Value")] int Value;
public Parameter(string ValueName, int Value)
{
this.ValueName = ValueName;
this.Value = Value;
}
}
[CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
public class ParameterList : List<Parameter>
{
}
public string Serialize(ParameterList plist)
{
var serializer = new DataContractSerializer(plist.GetType());
var output = new StringBuilder();
var xmlWriter = XmlWriter.Create(output);
serializer.WriteObject(xmlWriter, plist);
xmlWriter.Close();
return output.ToString();
}
public void Serialize_produces_2Levels_of_xml()
{
ParameterList p = new ParameterList
{
new Parameter("First", 1),
new Parameter("Second", 2),
};
var xml = Serialize(p);
}
}
如果你运行它,你将获得以下XML:
<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Serialize.Test">
<Parameter>
<Value>1</Value>
<ValueName>First</ValueName>
</Parameter>
<Parameter>
<Value>2</Value>
<ValueName>Second</ValueName>
</Parameter>
</MyClass>
答案 2 :(得分:1)
下面的工作使用MessageContracts虽然是'hack' - 它将“MyClass”元素归属于List成员,并排除了“MyClass”的包装命名空间。
[ServiceContract(Namespace="")]
public interface IService1
{
[OperationContract]
MyClass GetParameters();
// TODO: Add your service operations here
}
[DataContract(Namespace="")]
public class Parameter
{
[DataMember]
public string ValueName
{
get;
set;
}
[DataMember]
public int Value
{
get;
set;
}
public Parameter(string ValueName, int Value)
{
this.ValueName = ValueName;
this.Value = Value;
}
}
[MessageContract(IsWrapped = false, WrapperNamespace="")]
public class MyClass
{
[MessageBodyMember(Name = "MyClass", Namespace = "")]
public List<Parameter> Parameters
{
get;
set;
}
}