Abstract, Interface, and Attribute
-
Mazdak wrote: Serializable word express itself.It means you can seriallize this class. MSDN exapain these things very good,you can start from it. yes, [Serializable] is implemented as an attribute, but it really looks like an Interface, doesn't it? except that for technical reasons (one of the 2 interface "methods" is a constructor) it can't be an interface. Or something like that. What are the similarities and differences between something implemented as an Interface and something like [Serializable] which is implemented via attributes? ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
Actually, if you attribute your class with the
SerializableAttribute
, the default serialization will serialize public and private fields of your class. There is an interface,ISerializable
, that allows you to control the serialization so that you, the developer, controls what gets serialized and what doesn't. This does go along - like the original poster mentioned - with a constructor that has the signature(SerializationInfo, StreamingContext)
. This constructor can have any access modifier, but are common protected so that subclasses can pass serialization info to its base class. There are also other serialization interfaces that can be useful, such as theIDeserializationCallback
that allows you to perform any layout or hook-ups after serialization is complete, and theISerializationSurrogate
that - with anIFormatter
implementation allows you to serialize Types that are themselves serializable. You can also use aSerializationBinder
with the formatter to serialize from one Type to another, usingSerializationBinder.BindToType
. This seems especially handy when you have to upgrade a serialized file with older versions of Types.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Actually, if you attribute your class with the
SerializableAttribute
, the default serialization will serialize public and private fields of your class. There is an interface,ISerializable
, that allows you to control the serialization so that you, the developer, controls what gets serialized and what doesn't. This does go along - like the original poster mentioned - with a constructor that has the signature(SerializationInfo, StreamingContext)
. This constructor can have any access modifier, but are common protected so that subclasses can pass serialization info to its base class. There are also other serialization interfaces that can be useful, such as theIDeserializationCallback
that allows you to perform any layout or hook-ups after serialization is complete, and theISerializationSurrogate
that - with anIFormatter
implementation allows you to serialize Types that are themselves serializable. You can also use aSerializationBinder
with the formatter to serialize from one Type to another, usingSerializationBinder.BindToType
. This seems especially handy when you have to upgrade a serialized file with older versions of Types.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
So marking class Foo with [Serializable] magically adds expands Foo by implemnting the 2 ISerializable methods ending up with Foo : ISerializable? ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
So marking class Foo with [Serializable] magically adds expands Foo by implemnting the 2 ISerializable methods ending up with Foo : ISerializable? ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
No, you still have to implement
ISerializable
if you wish. Just attributing the class as I mentioned before withSerializableAttribute
serializes all private and public fields. ImplementingISerializable
is required if you want to control what gets serialized. See theISerializable
documentation for both more detail and an example.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Actually, if you attribute your class with the
SerializableAttribute
, the default serialization will serialize public and private fields of your class. There is an interface,ISerializable
, that allows you to control the serialization so that you, the developer, controls what gets serialized and what doesn't. This does go along - like the original poster mentioned - with a constructor that has the signature(SerializationInfo, StreamingContext)
. This constructor can have any access modifier, but are common protected so that subclasses can pass serialization info to its base class. There are also other serialization interfaces that can be useful, such as theIDeserializationCallback
that allows you to perform any layout or hook-ups after serialization is complete, and theISerializationSurrogate
that - with anIFormatter
implementation allows you to serialize Types that are themselves serializable. You can also use aSerializationBinder
with the formatter to serialize from one Type to another, usingSerializationBinder.BindToType
. This seems especially handy when you have to upgrade a serialized file with older versions of Types.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
Heath Stewart wrote: Actually, if you attribute your class with the SerializableAttribute, the default serialization will serialize public and private fields of your class. how does this happen? doesnt it require "somebody" to implement a default ISerializable for the class? or is it just done at runtime via reflection? [[need more smiley flavors for "huh??"!!!) ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
Heath Stewart wrote: Actually, if you attribute your class with the SerializableAttribute, the default serialization will serialize public and private fields of your class. how does this happen? doesnt it require "somebody" to implement a default ISerializable for the class? or is it just done at runtime via reflection? [[need more smiley flavors for "huh??"!!!) ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
If you'll read the documentation for
SerializableAttribute
, you'll see that the serialization infrastructure serializes private and public fields by default if a class is attributed (the class itself - inheriting the attribute doesn't make a derivative class serializable). This is done via reflection, yes. Note that your class must be attributed with theSerializableAttribute
even if it implementsISerializable
to be serializable. Implementing the interface just gives you explicit control over serialization of your Type.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
If you'll read the documentation for
SerializableAttribute
, you'll see that the serialization infrastructure serializes private and public fields by default if a class is attributed (the class itself - inheriting the attribute doesn't make a derivative class serializable). This is done via reflection, yes. Note that your class must be attributed with theSerializableAttribute
even if it implementsISerializable
to be serializable. Implementing the interface just gives you explicit control over serialization of your Type.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
ok, i guess i see how this is done-- pls correct me if i'm wrong: on invoking Formatter.Serialize, Formatter uses reflection to check whether ISerializable is implemented in the class of the object. if so it calls the interface. If not it uses reflection to serialize all the fields, checking for the NonSerialized as it goes. is that what happens? and if this is, how is that done efficiently enough to not take forever to serialize each two-bit-- i mean two-byte-- object in the graph? does BinaryFormatter perform some sort of run time analysis or "compilation" like regex? ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
If you'll read the documentation for
SerializableAttribute
, you'll see that the serialization infrastructure serializes private and public fields by default if a class is attributed (the class itself - inheriting the attribute doesn't make a derivative class serializable). This is done via reflection, yes. Note that your class must be attributed with theSerializableAttribute
even if it implementsISerializable
to be serializable. Implementing the interface just gives you explicit control over serialization of your Type.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
By decorating your class with the Serializable attribute you are just telling other classes that you pass it to that it is "auto-serializable", by which it is meant that it contains no volatile references (i.e. a SQLConnection object) or references to other classes that are not serializable. This way a remoting object (for example) knows that it does not need any special instructions to serialize/deserialize. DTrent
-
ok, i guess i see how this is done-- pls correct me if i'm wrong: on invoking Formatter.Serialize, Formatter uses reflection to check whether ISerializable is implemented in the class of the object. if so it calls the interface. If not it uses reflection to serialize all the fields, checking for the NonSerialized as it goes. is that what happens? and if this is, how is that done efficiently enough to not take forever to serialize each two-bit-- i mean two-byte-- object in the graph? does BinaryFormatter perform some sort of run time analysis or "compilation" like regex? ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
You should read Serializing Objects[^] in the .NET Framework. I think it'll help understand many of these concepts. As far as performance, it is true that reflecting all those fields and Types takes a while but it is necessary when crossing contexts (via Remoting) or serialing to streams for any other means. The process of serialization is actually pretty complex. If you're interested in the details, you should use ildasm.exe (if you know IL) or a good decompiler like .NET Reflector[^] to see how much of that is done. Our application I designed uses A LOT of Remoting in the Internet-deployed edition and it functions pretty fast - not much slower than the LAN version (and most people don't even notice). As far as I can tell, nothing is cached from serialization to serialization either because everything changes from call to call.
-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
By decorating your class with the Serializable attribute you are just telling other classes that you pass it to that it is "auto-serializable", by which it is meant that it contains no volatile references (i.e. a SQLConnection object) or references to other classes that are not serializable. This way a remoting object (for example) knows that it does not need any special instructions to serialize/deserialize. DTrent
i hadn't thought about the volatile references, thanks! ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
You should read Serializing Objects[^] in the .NET Framework. I think it'll help understand many of these concepts. As far as performance, it is true that reflecting all those fields and Types takes a while but it is necessary when crossing contexts (via Remoting) or serialing to streams for any other means. The process of serialization is actually pretty complex. If you're interested in the details, you should use ildasm.exe (if you know IL) or a good decompiler like .NET Reflector[^] to see how much of that is done. Our application I designed uses A LOT of Remoting in the Internet-deployed edition and it functions pretty fast - not much slower than the LAN version (and most people don't even notice). As far as I can tell, nothing is cached from serialization to serialization either because everything changes from call to call.
-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
thanks, yes i also use BinaryFormatter on pretty big objects and it seems remarkably efficient. Thanks for the suggestion on Reflector (do i also need to learn il?). Thanks for the insights and the Reflector fishing rod!! :-D ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
thanks, yes i also use BinaryFormatter on pretty big objects and it seems remarkably efficient. Thanks for the suggestion on Reflector (do i also need to learn il?). Thanks for the insights and the Reflector fishing rod!! :-D ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
Why not learn IL? You can never know too much. Besides, decompilers don't always do such a great job so you'll have to look at IL at some point to see what's really going on. At least knowing what the instructions do is important, which is also documented in the .NET Framework SDK.
-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
-
Why not learn IL? You can never know too much. Besides, decompilers don't always do such a great job so you'll have to look at IL at some point to see what's really going on. At least knowing what the instructions do is important, which is also documented in the .NET Framework SDK.
-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----
yikes! i guess you're right, that probably is the key to a lot of things i wish i knew how they were implemented, but i must admit it sounds fairly daunting!! also brings up a dumb question, is it obvious that the inner loop of the serialization (in BinaryFormatter?) would likely be written in IL not native x86? Thx! ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
-
yikes! i guess you're right, that probably is the key to a lot of things i wish i knew how they were implemented, but i must admit it sounds fairly daunting!! also brings up a dumb question, is it obvious that the inner loop of the serialization (in BinaryFormatter?) would likely be written in IL not native x86? Thx! ________________________________________ Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain. Then perhaps I'd deserve ya, and be even worthy of ya.. if I only had a brain!
All compilers targeting the CLR using pure managed code produce Intermediate Language, or IL. So yes, it is IL. In fact, the Managed C++ compiler is the only compiler publicly available from Microsoft that can produce native code in an assembly (known as mixed mode). But using an loop for serialization would be a poor idea. Recursion is most likely at work since for every Type that is added to the
SerializationInfo
, it has to be serialized, and then their Types, and so on so forth.-----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----