我有 2 个服务引用 (WCF)。
- 第一个 Visual Studio 使用 DataContractSerializer 生成代码
- 第二个,Visual Studio使用XmlSerializer生成代码
我无法更改网络服务器端的任何内容。
因此,我正在创建一个对象,该对象聚合来自两个引用的对象。
如何序列化此对象,使其遵守 DataContractSerializer 和 XmlSerializer 的序列化规范。 如果我使用 DataContractSerializer,我将像这样序列化引用 2 中的每个字段
<dataField>
而不是
<data>
因为它默认只序列化私有(private)字段(??)
如果我使用 XmlSerializer,引用 2 中的每个字符串数组都会像这样进行序列化
<myArray>
<string>test</string>
<string>test</string>
</myArray>
而不是
<myArray>
<url>test</url>
<url>test</url>
</myArray>
因为它忽略了 CollectionDataContractAttribute 属性,该属性指定如何序列化数组中的每个项目。
那么你的解决方案是什么?
我的第一个解决方案是将它们全部添加为良好的网络引用,但也许有一些不错的解决方案。
编辑:
这里是来自 1/Web 服务的类型声明(datcontract、wcf 样式)
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="productInformations", Namespace="http://abcedf.net/")]
[System.SerializableAttribute()]
public partial class productInformations : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
最佳答案
第一个问题:由于“添加Web引用”生成的类型被装饰为[Serializable]
默认情况下, DataContractSerializer
使用的可序列化模型是所有字段(公共(public)或非公共(public))都被序列化。如果用 [DataContract]
修饰类型以及您想要使用 [DataMember]
序列化的成员(属性) 。一个类型可以毫无问题地具有两个序列化器的属性,如下所示。
public class StackOverflow_7348240
{
[Serializable]
[DataContract(Name = "myRoot", Namespace = "")]
[XmlRoot(ElementName = "myRoot", Namespace = "")]
public class MyType
{
private string dataField;
[XmlElement(ElementName = "data")]
[DataMember(Name = "data")]
public string Data
{
get { return this.dataField; }
set { this.dataField = value; }
}
}
public static void Test()
{
MyType obj = new MyType { Data = "hello world" };
MemoryStream ms = new MemoryStream();
new DataContractSerializer(obj.GetType()).WriteObject(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
new XmlSerializer(obj.GetType()).Serialize(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
对于第二个问题,如果集合类型是另一个对象的成员,您还可以添加适当的属性(这次是用于 XML 序列化的属性),即 [XmlArray]
(指定集合名称)和 [XmlArrayItem]
(指定项目名称),并且您可以以相同的方式序列化相同的类型,如下面的示例所示。
public class StackOverflow_7348240_b
{
[DataContract(Name = "myRoot", Namespace = "")]
[XmlRoot(ElementName = "myRoot", Namespace = "")]
public class MyType
{
[DataMember(Name = "myArray")]
[XmlArray(ElementName = "myArray")]
[XmlArrayItem(ElementName = "url")]
public MyArray myArray;
}
[CollectionDataContract(Name = "myArray", Namespace = "", ItemName = "url")]
[XmlType(Namespace = "")]
[XmlRoot(ElementName = "myArray", Namespace = "")]
public class MyArray : List<string>
{
}
public static void Test()
{
MyType obj = new MyType { myArray = new MyArray { "one", "two" } };
MemoryStream ms = new MemoryStream();
new DataContractSerializer(obj.GetType()).WriteObject(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
new XmlSerializer(obj.GetType()).Serialize(ms, obj);
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
更新
我知道您想“手动”合并类型,但根据评论,情况并非如此。在这种情况下,如果您想同时使用添加 Web 引用 (AWR) 和添加服务引用 (ASR),那么您需要回退到通用序列化程序,即 XmlSerializer
。 AWR总是使用XmlSerializer
(XS),而 ASR 可以同时使用该和 DataContractSerializer
(DCS)。 DCS 是 ASR 的默认设置,但您可以将其更改为使用另一种。您有两个选择:
- 使用 svcutil.exe(而不是 ASR),并传递/serializer:XmlSerializer 命令行
- 添加服务引用后,打开Reference.svcmap文件(您可能需要选中项目的“显示所有文件”选项),然后更改选项
<Serializer>
来自Auto
至XmlSerializer
,然后选择“更新服务引用”。
关于.net - 使用 DataContractSerializer 和 XmlSerializer 进行 XML 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7348240/