Как сериализовать класс со свойством объекта типа, заполненного массивом - PullRequest
2 голосов
/ 28 февраля 2012

После поиска 99% сети я все еще застрял в следующем вопросе. У меня есть веб-сервис, который должен соответствовать WSDL, предоставленному компанией-партнером. Вызов метода этого сервиса приводит к (сложному) классу. К сожалению, ошибка сериализации возникает при вызове службы.

Я точно определил проблему, но не могу придумать (и найти) ее решение. Поскольку я зависим от 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: добавлены атрибуты сериализации, но ошибка остается

Ответы [ 3 ]

1 голос
/ 01 марта 2012

Похоже, вы не можете добавить массив типов к object и сериализовать его. Решением было создать контейнерный класс, который, как следует из названия, содержит массив. Таким образом, вы можете назначить класс контейнера для object и сериализовать его все.

В дополнение к моему случаю меня ввела в заблуждение объектная модель, созданная утилитой wsdl.exe, поскольку класс контейнера является лишь техническим решением для добавления массива в object. Этот контейнерный класс также был создан, поэтому все было уже готово для использования. Только после того, как опробовал свой класс контейнера, я заметил уже созданный класс контейнера. Потерял много времени на это, к сожалению ...

0 голосов
/ 20 сентября 2018

Это старый вопрос, но у меня была та же проблема и я нашел другое решение, поэтому я решил поделиться, если это поможет кому-то еще.

Я обнаружил, что могу добавить атрибуты, чтобы разрешить массивы определенных типов. Для решения проблемы выше класс 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[], как в тестовом примере вопроса.

0 голосов
/ 28 февраля 2012

Вы должны пометить ваши классы как

[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 класс), который вам нужно будет сделать вручную, реализовав соответствующие интерфейсы: ISerializable и IDeserializationCallback , бота добавлена ​​в MyObject класс.

...