3

I am trying to learn to use C# serialization as a way to save objects into files that can be reloaded back into objects.

A plain class like this that I tested

[Serializable()]
public class PlainClass
{
    public string Name;
    private int Age;
    protected decimal Price;
}

Can be directly BinaryFormatter.Serialize() and BinaryFormatter.Deserialize() without errors. (by the way, the private and protected properties also get serialized although the docs say only public)

But the moment it implements ISerialization or inherit some class like Hashtable that implements ISerialization, the you-know-what deserialization constructor is required. The word or concept of "implement" becomes a misnomer because Hashtable does not actually implement that constructor.

Is there a way to fall back to the "auto" Serialization/Deserialzation provided only by the attribute? Or is there an easier way to write info.GetValue() for a hundred properties in a class?

2
  • 1
    in the documentation it states "When you use the Serializable attribute, .NET run-time serialization uses reflection to identify the data that should be serialized. All nontransient fields are serialized, including public, private, protected, and internal fields. XML serialization uses reflection to generate special classes to perform the serialization." (msdn.microsoft.com/en-us/library/ff650685.aspx) Commented Aug 17, 2011 at 7:10
  • @Yahia point taken. but I swear there was a MSDN page (which I cannot find now) that says the serialization works for public properties and member. Maybe I misunderstood the context. Commented Aug 17, 2011 at 7:19

2 Answers 2

4

There is a lot of confusion in your post:

by the way, the prive and protected properties also get serialized although the docs say only public)

I suspect you are confusing two different serializers; BinaryFormatter is and always has been documented as field-centric. It doesn't distinguish between public/private, and it never looks at properties: only fields. XmlSerializer, by contrast, only looks at public properties and fields.

The word or concept of "implement" becomes a misnomer because Hashtable does not actually implement that constructor.

Yes it does; it is a protected constructor:

protected Hashtable(SerializationInfo info, StreamingContext context)
{...}

If you inherit Hashtable you can chain to this constructor:

protected YourType(SerializationInfo info, StreamingContext context)
     : base(info, context)
{ /* your extra data */ }

Note, however, that you probably shouldn't be using Hashtable much unless you are on .NET 1.1.

Is there a way to fall back to the "auto" Serialization/Deserialzation provided only by the attribute?

No; none.

Or is there an easier way to write info.GetValue() for a hundred properties in a class?

In the case of inherited data, you could chain the base-constructor or switch to encapsulation instead of inheritance - either avoids the need to worry about data other than your own.

Note, however, that I almost always guide against BinaryFormatter - it can be vexing, and is quirky with versioning. For every annoyance with BinaryFormatter, I use protobuf-net (I would, since I wrote it) - this generally makes serialization much more controlled (and more efficient), and includes an ISerializable hook if you really want to use BinaryFormatter (i.e. it can use BinaryFormatter as the wrapper, but with a protobuf-net payload).

Sign up to request clarification or add additional context in comments.

4 Comments

thanks for the clarifications. If I now understand correctly, the serialization looks only at the class being serialized and the protected constructor is therefore "hidden". I will check out protobuf as an alternative. Thanks again!
@Jake not quite - it is hidden because you shouldn't need it in regular usage; you can still use it when inheriting, as shown. No "looks only at the class being serialized" - well, it looks at the object, which includes the entire hierarchy. If using ISerializable it assumes you will be using ctor-chaining to populate the base values.
sorry marc, firstly, many thanks for your work, I can see that it is promising. but lack of documentation is driving me nuts ;p if do I really need to ProtoMember() for a hundred properties? sad
@Jake the limiting factor there is availability; alas it doesn't write itself. Adding ProtoMember is indeed one option - there are others, if you know it isn't going to change - for example you can infer the tag order by name, but then DON'T ADD PROPERTIES. Note that explicit member markers are not unique - WCF (DCS) works better with such, too.
0

Hashtable/Dictionary requires the implementation of the respective methods...

To work around that you would have to implement a separate class to hold the Dictionary data and provide an IList interface instead which in turn need not work on TKeyValuePair but with a separately implemented class with Key/Value (refer to http://blogs.msdn.com/b/adam/archive/2010/09/10/how-to-serialize-a-dictionary-or-hashtable-in-c.aspx)...
As you can see from the start of my explanation - this is nothing you would usually want to do...

There are better serialization solutions out there - see for a very good one http://code.google.com/p/protobuf-net/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.