如何序列化具有填充数组的对象类型属性的类

Posted

技术标签:

【中文标题】如何序列化具有填充数组的对象类型属性的类【英文标题】:How to serialize a class with a property of type object filled with an array 【发布时间】:2012-03-18 00:37:33 【问题描述】:

在搜索了 99% 的网络后,我仍然卡在以下问题上。我有一个必须遵守合作伙伴公司提供的 wsdl 的 Web 服务。调用此服务的方法会产生一个(复杂的)类。不幸的是,调用服务时会引发序列化错误。

我已查明问题,但想不出(并找到)解决方案。因为我依赖于提供的 wsdl,所以我无法更改复杂的类结构。希望有人知道我错过了什么。这是重现我的问题的示例代码:

[System.SerializableAttribute()]
public class MyObject

    public int Id  get; set; 
    public object Item  get; set;     // <---- Note type *object* here


[System.SerializableAttribute()]
public class MyItem

    public int Id  get; set; 
    public string Name  get; set; 


[TestClass]
public class SerializationTest

    [TestMethod]
    public void Serializing()
    
        MyObject myObject = new MyObject  Id = 1 ;
        myObject.Item = new MyItem[]  new MyItem  Id = 1, Name = "Test"  ;

        string serializedString = SerializeObjectToXmlString(myObject, new [] typeof(MyItem));

        Assert.IsFalse(String.IsNullOrWhiteSpace(serializedString));
    

    /// <summary> 
    /// This method serializes objects to an XML string using the XmlSerializer 
    /// </summary> 
    private static string SerializeObjectToXmlString(object theObject, Type[] types)
    
        using (var oStream = new System.IO.MemoryStream())
        
            var oSerializer = new System.Xml.Serialization.XmlSerializer(theObject.GetType(), types);

            oSerializer.Serialize(oStream, theObject);  // <- Here the error is raised

            return System.Text.Encoding.Default.GetString(oStream.ToArray());
        
    

在 Try/Catch 中,调用方法 Serialize() 后会引发错误。此错误的详细信息是:

InvalidOperationException was unhandled by user code
- There was an error generating the XML document.
  The type MyItem[] may not be used in this context.

我的开发环境包括 Visual Studio 2010、.Net Framework 3.5。

编辑#1:添加序列化属性但错误仍然存​​在

【问题讨论】:

【参考方案1】:

你应该把你的类标记为

[Serializable]
public class MyObject

  public int Id  get; set; 
  public MyItem[] Item  get; set;     // <---- Note type *object* here


[Serializable]
public class MyItem

  public int Id  get; set; 
  public string Name  get; set; 

序列化未知对象(MyObject 类的Item)您需要通过实现适当的接口手动执行: ISerializable 和 IDeserializationCallback,都添加到 MyObject 类中。

【讨论】:

是的,你说得对,我需要添加这些属性。我忘记在我的示例中添加它们,但在我的真实代码中确实有它们。不幸的是,这并不能解决问题。我将更新上面的代码示例。 我认为问题出在 MyObject 声明上:将 public object Item 更改为 public MyItem[] Item 是的,这确实会产生并发症。唯一的问题是我无法更改它,因为类结构是从 wsdl 生成的。在我的示例中,object 还包含 MyItem[],但必须能够包含其他两种(更简单的)类型。【参考方案2】:

您似乎无法将类型数组添加到 object 并对其进行序列化。解决方案是创建一个容器类 - 正如名称所说 - 包含数组。这样您就可以将容器类分配给object 并将其全部序列化。

除了我的情况,我被 wsdl.exe 实用程序创建的对象模型误导了,因为容器类只是将数组添加到 object 的技术解决方案。这个容器类也被创建了,所以一切都已经可以使用了。只有在尝试了我的自定义容器类之后,我才注意到已经创建的容器类。不幸的是,在这件事上浪费了很多时间......

【讨论】:

【参考方案3】:

这是一个老问题,但我遇到了同样的问题并找到了不同的解决方案,所以我想我会分享一下,以防它帮助其他人。

我发现我可以添加属性来允许特定类型的数组。针对上述问题,MyObject类可以编辑如下:

[System.SerializableAttribute()]
public class MyObject

    public int Id  get; set; 
    [XmlElement(Type = typeof(object), ElementName = "Item"), //added
        XmlElement(Type = typeof(MyItem[]), ElementName = "Item_asArrayOfMyItem")] //added
    public object Item  get; set;     // <---- Note type *object* here

之前序列化的任何内容看起来仍然相同,但现在MyObject 可以序列化,即使Item 的类型为MyItem[],就像在问题的测试用例中一样。

【讨论】:

以上是关于如何序列化具有填充数组的对象类型属性的类的主要内容,如果未能解决你的问题,请参考以下文章

如何在objective-c中比较两个具有很多属性的对象

使用“多类型”属性序列化 Json 对象

Delphi的类和对象之数组属性和属性的索引

如何反序列化具有相同名称但不同类型的 API 响应

无法将当前 JSON 数组(例如 [1,2,3])反序列化为具有复杂和嵌套对象的类型

无论如何在 C# 中反序列化之前检查对象的类类型?