2010-04-22 3 views
2

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

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

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

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

Edit:

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

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

+2

Какой сериализатор вы используете? 'BinaryFormatter'? 'XmlSerializer'? 'DataContractSerializer'? «Домашний органический сериализатор Боба»? Также есть ли какие-либо «события»? –

+0

См. Мое редактирование; и да, есть события, связанные где-то вдоль линии, ведущей к вызову binaryFormatter.Deserialize; вы видите какую-либо связь? –

+0

Интерфейс используется для определения того, может ли класс сказать, что он может быть сериализован, если у вас есть список ссылок на основе интерфейса, где интерфейс не помечен как сериализуемый, возможно, код сериализации пытается сказать вам, что вы можете потенциально объекты здесь, с которыми он не может справиться? Даже если ваш текущий график объектов A-OK. –

ответ

-1

Легкий способ (Хотя некрасиво) Оберните список:

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; } 
} 
+0

Не понимаю. Класс, реализующий IListMember **, является ** [Serializable] - почему я хотел бы создать дополнительный абстрактный базовый класс? –

2

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

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

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

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

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

+0

Нет, не правда; мы действительно используем BinaryFormatter; и он действительно может сериализовать классы, даже если они объявлены только через интерфейс. ** тип ** класса остается конкретным типом, который, как вы говорите, поддаётся отражению; Тот факт, что он объявлен в свойстве класса только через интерфейс, не меняет этого. –

Смежные вопросы