Исключение интерфейса "не помечен сериализуемым атрибутом" - PullRequest
2 голосов
/ 23 апреля 2010

У меня есть очень странное исключение в моем приложении на C #: при попытке десериализации класса, содержащего универсальный List<IListMember> (где записи списка определяются интерфейсом), генерируется исключение, сообщающее, что «тип ... IListMember» не помечен атрибутом serializable "(формулировка может немного отличаться, мой VisualStudio не на английском языке).

Теперь интерфейсы не могут быть Serializable; класс, фактически содержащийся в списке, реализующий IListMember, равен [Serializable]; и да, я проверил, что IListMember на самом деле определяется как интерфейс, а не случайно как класс!

Я пытался воспроизвести исключение в отдельном тестовом проекте, содержащем только класс, содержащий список и члены, но там он успешно сериализуется и десериализуется: /

У кого-нибудь есть хорошие идеи о том, что это может быть?

Edit:

Мы используем BinarySerializer; и я повторяю, при извлечении в тестовый проект класс сериализуется счастливо. Поэтому мне не нужен обходной путь для сериализации класса, содержащего List<IThing>, так как в целом это работает нормально (если фактические классы, реализующие IThing, являются сериализуемыми); я ищу причины, по которым не может работать именно в это время ...

Я сейчас ввел обходной путь (сериализация каждого члена списка по отдельности вместе с количеством записей и воссоздание List вручную), но очень хотел бы выяснить, что это может быть для дальнейшего использования.

Ответы [ 2 ]

2 голосов
/ 23 апреля 2010

Неважно, что класс, поддерживающий интерфейс, является сериализуемым. Интерфейсы не могут быть сериализованы, точка.

Чтобы десериализовать , сериализатору необходимо иметь возможность создавать конкретный тип, и он определяет этот тип, отражая поля / свойства класса, подлежащего десериализации.

Если тип одного из этих свойств является интерфейсом, то он никогда не сможет создать конкретный тип для назначения этому члену. Все, что он видит, это интерфейс, он не знает, какой класс первоначально реализовал его, когда данные были сериализованы.

Если вы хотите, чтобы класс был сериализуемым, то каждый класс в графе объектов должен иметь конкретный тип. Интерфейсы не допускаются.

(Постскриптум: На самом деле, я вроде как солгал, BinaryFormatter может сериализовать / десериализовать напрямую в / из типов интерфейса, но я сильно подозреваю, что это не то, что здесь используется.)

0 голосов
/ 23 апреля 2010

Легкий путь (хотя и уродливый) Оберните свой список:

public ListMemberCollection : List<IListMember>, ISerializable
{
    // Implement ISerializable Here
}

Альтернативный способ (хотя и лучше) AbstractBaseClass:

[Serializable]
public ListMemberBase : IListMember
{
   // Implement abstract versions of everything
}

Возможность ?: (на вашем другом классе)

class TheClassYoureSerializing
{
   [Serializable]
   public List<IListMember> list { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...