【问题标题】: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:添加序列化属性但错误仍然存​​在

【问题讨论】:

    标签: c# visual-studio-2010 serialization .net-3.5


    【解决方案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)您需要通过实现适当的接口手动执行: ISerializableIDeserializationCallback,都添加到 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[],就像在问题的测试用例中一样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-03
        • 2023-04-03
        • 1970-01-01
        • 2021-12-09
        • 2014-08-14
        相关资源
        最近更新 更多