I'm storing some objects in my viewstate and I was wondering if there are any disadvantages to making a class Serializable?
Is it bad practice to make all of the classes Serializable?
Firstly. Avoid viewstate.
Generally serialization (textual) is used for transferring objects.
You should avoid marking any class as serializable that is not a DTO (Data transfer object) or message class. We do this for several reasons. What ever picks up your class in serialized format may not have the method information (which is in the original assembly) of a non DTO class. Secondly, a class may reference a resource (DB connection, file handle, etc) Do NOT serialize these, since de serialization does not re-establish resource connections and state, unless explicitly designed for, but is still a bad idea.
So in summary: Do NOT serialize when you have contextual methods and storing data for a thrid party to use. (Like a service response with methods is a bad idea). And do NOT serialize when the class contains a resource reference. Keep your serializable object clean from methods as much as possible. This might involve a little re factoring into a service type pattern.
Do serialize DTO's and messages.
This is more of a design choice.
It is a good practice to make all classes that are actually Serializable as Serializable. I would just use common sense, and set it for those classes that are intended for crossing process boundaries (DTO classes).
So it those classes which:
All their properties are simple types
And if they have complex properties, their types themselves are serializable
Marking it as [Serializable] (or ISerializable) is necessary for anything using BinaryFormatter, which may well include viewstate under the default configuration. As for good vs bad practice... well, most classes don't need to be serialized, and IMO even when they are, using BinaryFormatter is not always the best choice*. And specifically, marking it as both [Serializable] and [DataContract] will cause an exception IIRC.
*=actually, IMO BinaryFormatter is very rarely a good choice, but I might be biased... and I deliberately don't use viewstate ;p
Related
I wonder if there is any possibility of serializing a class described in a topic.
Suppose we have someone's library that is shared as binary DLL file. Additionally a creator of this lib created a class that is not Serializable. How to serialize such a class? I know I can create a twin-class that contains all the poperties etc. that can be serialized. But is there any other, easier solution to do this? How do you serialize classes that are "not yours" and are stored as binary only?
The 3rd party class is an implementation detail; frankly, it is a very bad idea to involve this in your serialization, as you are then completely fenced into a corner, and can never change implementation. You would also face significant risk of versioning issues - something that BinaryFormatter simply doesn't handle well.
It might not be what you want to hear, but I offer two recommendations:
do not serialize implementation details; serialize the data (only); this may indeed require you to write a DTO that mirrors the implementation, but this is usually a trivial job
make sure you understand the implications of BinaryFormatter; frankly, I never recommend it - it has... glitches.
As for workarounds: you can investigate serialization surrogates, but that isn't a trivial thing to do inside BinaryFormatter, and is basically just a re-statement of the first bullet.
If it was me (although I am hugely biased), I would change serializer; protobuf-net (disclosure: I'm the author) works as a binary serializer, and has easy-to-implement support for surrogates if the third-party model is already coupled to your model.
I'm using Azure Cache preview and need to make some classes Serializable.
Is there any disadvantage of making class to be Serializable - such as performance issue?
[Serializable]
public class MyClass {}
I found few related questions, but they are not about disadvantages.
Are all .NET exceptions serializable?
Drawbacks of marking a class as Serializable
Thank in advance
No, there is no intrinsic overhead simply in being marked as [Serializable]. The only problem I'd have is that BinaryFormatter and NetDataContractSerializer are lousy serializers, and most other serializers aren't interested in this flag (ok, I may be biased)
Assuming you're talking about the cost of using the Serializable attribute rather than the actual serialization process, one drawback would be that a third party would normally assume that the class is designed to be serializable. Whilst this may be the case, if you're just marking it serializable for the sake of it (and if there's a chance a third party might interact with it), then you'd probably want to spend time ensuring that the class is suited to be serialised in an efficient manner. So it's more of a resource tradeoff than a technical one, from that point of view.
From a technical standpoint, as Marc Gravell said, just using the attribute won't really have any overhead.
On my own object I can add the metatag [Serializable] to make it serializable. Now I use a 3rd party library that I need to be serializable. I inspected the code and it should not be a problem. Is there a way to fix this without altering the 3rd party code?
My advice would be: serialize data, not implementation. The fact of the existence of a 3rd-party object is nothing to do with the data; that is an implementation detail. As such, I always offer the same advice: if serialization ever gets complex, the first thing to do is to introduce a separate DTO model that represents the data in isolation of the implementation, and just map the current state to that DTO. This allows you to handle implementation changes without impact on the storage, and allows otherwise non-serializable objects to be serialized.
Some serializers offer workarounds - for example with protobuf-net you can a: supply the serialization information for any type at runtime, and b: supply a "surrogate" to use automatically when it gets tricky, but - using a DTO model is simpler and easier to maintain.
Your use of [Serializable] suggests BinaryFormatter; in my opinion, this is almost never a good choice for any kind of storage, since BinaryFormatter relies on implementation details. It works nicely for passing data between two in-sync app-domains, though
If the types are public you should be able to use the XmlSerializer to do what you want.
There's more information on this here
Serializes and deserializes objects into and from XML documents. The
XmlSerializer enables you to control how objects are encoded into XML.
Exactly take your subclass and make it serializable.
[Serializable] public class Foo: Bar {}
Write an adapter or be prepared to do something more extreme like disassembling the assembly, injecting the serializable attribute and reassembling.
whenever I try to serialize an object that has an IEnumerable collection I get a big dirty error telling me it can't serialize it because it's an interface. Now I get why it's happening but it raises some other questions for me. Like if I intend on having collections within my objects AND I want to serialize them do I need to resort to
Using List<>, CollectionBase, ReadOnlyCollectionBase in my objects.
Making my objects implement the IXmlSerializable interface.
Decorating my classes with horrible attributes.
Writing my own serializer.
What is the best practice way to go?
Speaking as a serializer author, I know exactly why it gets very hard to robustly work just from IEnumerable<T>, especially for "get-only" properties. You might try IList<T> (although it wouldn't amaze me if it wants a concrete type such as List<T>/T[]), but I suspect the real problem here is that you trying to use one model to do two things, and are unhappy at having to compromise to do it.
Fine: if you don't want to compromise your domain model, write a separate DTO model that is used for serialization, and just map between them. This is usually trivial, and will allow the serializer and the domain model to each excel at their one job. It will also help immensely when you need to "version" the system or introduce a different serializer (JSON, protobuf, etc).
Re your bullets:
I suspect any concrete list type (even your own) with Add etc will work
I don't recommend that to anyone - it is painful to do reliably
nothing ugly about attributes; again, I suspect your complaint is about attributing your domain model - so: fine, don't do that - have a separate model; you can actually do all this at runtime, but it is much more work (see XmlAttributeOverrides, but watch out for leaking assemblies if you do this)
don't underestimate how much work that is; the basics - seductively easy; but the non-trivial scenarios can be brutal
For use interface or derivade classes you MUST use the XmlSerializer(Type type, Type[] extraTypes) constructor.
In extraTypes you MUST include all possible classes which can implement the interfaces in your classes.
Based on my understanding, SerializableAttribute provides no compile time checks, as it's all done at runtime. If that's the case, then why is it required for classes to be marked as serializable?
Couldn't the serializer just try to serialize an object and then fail? Isn't that what it does right now? When something is marked, it tries and fails. Wouldn't it be better if you had to mark things as unserializable rather than serializable? That way you wouldn't have the problem of libraries not marking things as serializable?
As I understand it, the idea behind the SerializableAttribute is to create an opt-in system for binary serialization.
Keep in mind that, unlike XML serialization, which uses public properties, binary serialization grabs all the private fields by default.
Not only this could include operating system structures and private data that is not supposed to be exposed, but deserializing it could result in corrupt state that can crash an application (silly example: a handle for a file open in a different computer).
This is only a requirement for BinaryFormatter (and the SOAP equivalent, but nobody uses that). Diego is right; there are good reasons for this in terms of what it does, but it is far from the only option - indeed, personally I only recommend BinaryFormatter for talking between AppDomains - it is not (IMO) a good way to persist data (to disk, in cache, to a database BLOB, etc).
If this behaviour causes you trouble, consider using any of the alternatives:
XmlSerializer, which works on public members (not just the fields), but demands a public parameterless constructor and public type
DataContractSerializer, which can work fully opt-in (using [DataContract]/[DataMember]), but which can also (in 3.5 and above) work against the fields instead
Also - for a 3rd-party option (me being the 3rd party); protobuf-net may have options here; "v2" (not fully released yet, but available as source) allows the model (which members to serialize, etc) to be described independently of the type, so that it can be applied to types that you don't control. And unlike BinaryFormatter the output is version-tolerant, known public format, etc.