views:

198

answers:

2

I have a very odd exception in my C# app: when trying to deserialize a class containing a generic List<IListMember> (where list entries are specified by an interface), an exception is thrown reporting that "the type ...IListMember is not marked with the serializable attribute" (phrasing may be slightly different, my VisualStudio is not in English).

Now, interfaces cannot be Serializable; the class actually contained in the list, implementing IListMember, is [Serializable]; and yes, I have checked that IListMember is in fact defined as an interface and not accidentally as a class!

I have tried reproducing the exception in a separate test project only containing the class containing the List and the members, but there it serializes and deserializes happily :/

Does anyone have any good ideas about what it could be?

Edit:

We are using a BinarySerializer; and I repeat, when extracted to a test project the class serializes happily. So I do not need a workaround to serialize a class containing a List<IThing>, as in general this works fine (as long as the actual classes implementing IThing are serializable); what I am looking for is reasons why it might not work this particular time...

I have now put in a workaround (serializing each list member individually, together with the number of entries, and recreating the List by hand), but would really like to find out what it could be for future reference.

A: 

The Easy Way (Although ugly) Wrap your list:

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

The Alternative Way (Although better) AbstractBaseClass:

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

A possibility?: (On your other class)

class TheClassYoureSerializing
{
   [Serializable]
   public List<IListMember> list { get; set; }
}
Aren
I don't understand. The class implementing IListMember **is** [Serializable] - why would I want to make an additional abstract base class?
Joel in Gö
+1  A: 

It doesn't matter that the class backing the interface is serializable. Interfaces cannot be serialized, period.

In order to deserialize, the serializer needs to be able to instantiate a concrete type, and it determines this type by reflecting on the fields/properties of the class-to-be-deserialized.

If the type of one of those properties is an interface, then it will never be able to construct a concrete type to assign to that member. All it sees is the interface, it has no idea which class originally implemented it when the data was serialized.

If you want the class to be serializable, then every class in the object graph must be a concrete type. No interfaces allowed.

(Postscript: Actually, I sort of lied, the BinaryFormatter can serialize/deserialize directly to/from interface types, but I strongly suspect that's not what's being used here.)

Aaronaught
Nope, not true; we are indeed using BinaryFormatter; and it can indeed serialize classes even if they are declared only via an interface. The **type** of the class remains the concrete type, which is, as you say, amenable to reflection; The fact that it is declared in the class property only via an interface does not change this.
Joel in Gö