I am storing type related information in a dictionary, e.g.

Dictionary<Type, int> TypeInformation;

TypeInformation[typeof(OneOfMyOwnClasses)] = 42;

Then I (binary) serialize the state of my application, including the above dictionary.

What happens to the type objects if I change OneOfMyOwnClasses in code? Under which conditions do the type objects stay the same after deserialization? I.e. when will

if (TypeInformation[typeof(OneOfMyOwnClasses)] == 42)
    MessageBox.Show("Yahoo !!!");

give an affirmative result even after I deserialize the state of my app?

  • Is a change of method bodies guaranteed to give the same type objects between different runs?
  • Do changes of private method or field names change anything about the type objects?
  • Changes of public method (or field) names?
  • Change of namespace or assembly?
  • Changes of class name itself? (supposedly not... ;-) )

Finally, given all that, are there any good reasons not to serialize type infos and is there a better yet more involved way (like creating GUID's and such)?

1 Answers

Marc Gravell On Best Solutions

Assuming you mean BinaryFormatter, then:

  1. changing the type, namespace, or assembly identity of a type will break the serializer if you are storing instances of the type, or the Type object itself
  2. changing the names or types of the fields on a type will break the serializer, if you are storing instances of that type

In both cases there are ways to kinda fix it by jumping through complex hoops, but it usually isn't a good idea to try. In my considered experience, BinaryFormatter simply isn't a good choice except in very specific scenarios (in particular, RPC between two running applications that must by necessity be running the exact same code - such as app-domain isolation), and if your intent is general purpose storage, you are usually better using anything else. My particular leaning is towards protobuf-net (which is "binary" in that it implements google's binary "protocol buffers" format), but I'm admittedly biased. JSON and XML are also good options in terms of portability, although they almost always have larger output and (slightly) slower processing.

Note that most serializers, when serializing a Type object, will use the fully-qualified name, so point 1 above will apply to most, although per-serializer ways of changing that may exist. Frankly, though, I'd say that if you're serializing a Type instance, you're doing something wrong, and it would be better to do that as a manual keyed lookup against some external reference (which could be via an attribute on the type, for example). For example:

class OneOfMyOwnClasses {...}

then use reflection to get the SomeMarkerAttribute instance (in some cached way), such that you actually store:

Type type = ...
string key = GetMarkerFromType(type); // "abc"
Dictionary<string, int> TypeInformation;
TypeInformation[key] = 42;