compileinplace with non-serializable type - serializable

I am using CompileInPlace to handle preparing to serialize a type based on its runtime type since at compile time I only know it is derived from object.
Unlike PrepareSerialize, however, I get no indication with CompileInPlace if the type passed to it is not serializable. Instead, I only get an exception later when I try to serialize the object.
Is there some way to verify that the object is actually serializable ahead of time, i.e. when I call CompileInPlace?

Related

Custom .NET Serialization doesn't seem to work

I am using BinaryFormatter to serialize a collection of objects of class A stored in a System::Collections::Generic::List<A^>^. I have added the [Serializable] tag and have implemented ISerializable in class A (both GetObjectData and the special constructor). When deserializing, I find that the list is deserialized and contains the same number of elements as was serialized. However, each of these elements is a null reference.
I've checked for thrown exceptions and am sure that it is not the case. I have checked to ensure that the special constructor of the form A(SerializationInfo ^info, StreamingContext context) is called the correct number of times during deserialization but these re-constructed objects are not being referenced from the deserialized collection.
I also replaced the System::Collections::Generic::List<A^>^ with array<A^>^ and I'm still getting the same results. The array has the correct number of elements but each element is a null reference.
Anyone who has seen a similar problem? Any clues?
The problem was that any objects referred to within child objects need not have been completely deserialized immediately after a GetValue call. In my case, the generic List had not yet been completely deserialized and so contained only null references. I finally used IDeserializationCallback to execute code after the object graph had been completely deserialized.
From your description it sounds like the items within your list are possibly non-serializable; if you have control over that class can you verify if it is also tagged as serializable?
Also, have you tried using an XmlFormatter to be able to visually check the serialized data to see just how it's being built? It might provide some insight into whether the problem is occuring during serialization or deserialization.

Can a IFormatter deserizalize a object of an unreferenced type?

Supose I serialized a third party library type object with BinaryFormatter. An assemby that does not references this library tries to deserialize the bytes. Will it work?
I do not expect to it be cast to the correct type, I just want to retrieve it as an object instance so I can group it and serialize it again.
This should work fine, but only if that library is deployed with the app. You don't need a direct reference to it.
During serialization, the BinaryFormatter stores the full assembly name (display name, public key token, version number) along with the type information. This is enough information for the deserializer to go off and load that assembly again. Note that path information is not stored, hence the need to deploy the assembly in the app that does the deserialization.
No; if the type itself isn't referenced (in some way by some loaded assembly), then it can't be instantiated. Even if you don't need (or want) to reference the instance in a strongly-typed way, the object itself must still be an instance of that type.
If the assembly is available (and discoverable), then it will be loaded, but in a strict sense no, you won't be able to deserialize a type from a completely unreferenced assembly.
If you are only trying to temporarily obtain the serialized information so that you can group it, can you just read the raw bytes from the serialized stream and group them? Maybe into a List<byte[]> instance? This assumes that the final destination can make some assumptions about the information represented by each byte array.
No, it won't work, in order to deserialize a object you need to reference the assembly where the object is defined.
Yes, if you create a serialization binder, you can deserialize the type to a different type. But you won't be able to instantiate an instance of the original type without it's definition (to which you'd be required to have the assembly on hand)

Cannot deserialize an object using a converter?

Given a JSON string of the form {"$type":"MyType, MyAssembly","seed":0"}, why can't JsonConvert.DeserializeObject utilize the JsonConverter associated with "MyType"?
I've tried decorating the MyType class with a [JsonConverter(typeof(MyType))] attribute. Doesn't work. The custom JsonConverter's ReadJson method is never called.
I've tried adding the custom converter to the serializer's settings Converters collection and made sure the CanConvert method returns true for 'MyType' and the CanRead method returns true. Doesn't work. Neither the converter's CanConvert nor its ReadJson method is ever called.
The DeserializeObject method needs to be able to deserialize a JSON string containing an object whose type is unknown at compile time, but whose type is embedded in the JSON object via the special "$type" member. So don't suggest using DeserializeObject<T> or point out that it works for members, whose type is identified in the contract before hand.
FYI, this problem generalizes to cases where the deserialization needs to identify the object type solely from the embedded "$type" member, so for example, it also fails to resolve a converter if the JSON object is in an untyped JSON array, not just at the top-level.
Basically, an object cannot survive a round trip through the serialization/deserialization process, because although the WriteJson method will be called for the Converter when SerializeObject is called, when you subsequently pass the JSON string to DeserializeObject, it fails to call the converter's ReadJson method, and instead constructs an new instance and uses the basic member population routines.

What is the CLR doing “automagically” when a type is annotated [serializable]?

I understand that when you annotate a type with [serializable] it tells the CLR that this type can be serialized.
I don't like this seeming like "black box" magic to me. I want to know what it does when I mark it with this attribute.
In addition it would be helpful to know what it then does when I actually try to serialize an object.
P.S. if the answer to this question can pertain to the handling of any attribute, please feel free to edit my question title and question to reflect this. Thanks.
The Common Language Runtime (CLR) manages how objects are laid out in memory and the .NET Framework provides an automated serialization mechanism by using reflection. When an object is serialized, the name of the class, the assembly, and all the data members of the class instance are written to storage. Objects often store references to other instances in member variables. When the class is serialized, the serialization engine keeps track of all referenced objects already serialized to ensure that the same object is not serialized more than once. The serialization architecture provided with the .NET Framework correctly handles object graphs and circular references automatically. The only requirement placed on object graphs is that all objects referenced by the object that is being serialized must also be marked as Serializable. If this is not done, an exception will be thrown when the serializer attempts to serialize the unmarked object.
this part of this article: http://msdn.microsoft.com/en-us/library/ms973893.aspx
The only thing that happens is that typeof(MyClass).IsSerializable will be true. Then there is a statement saying if (!typeToBeSerialized.IsSerializable) throw ... in the code that does the actual serialization.

.NET Binary Serialize object with references to other objects . . . what happens?

If you have an object instance A that references other objects (for example instances B and C), and you binary serialize A to a file, what happens? Do you now have serialized data that includes A, B and C?
How does it work exactly? What will I get if I deserialize the data? A, B, and C??
(Feel free to include internal workings explanations as well).
All of the references to other objects will be serialized as well. If you deserialize the data, you will end up with a complete, working set of its data, including objects A, B, and C. That's probably the primary benefit of binary serialization, as opposed to XML serialization.
If any of the other classes your object holds a reference to are not marked with the [Serializable] attribute, you'll get a SerializationException at run-time (the image of which was shamelessly stolen from the web; run-time errors don't even look like this anymore in the current versions of VS):
Further than that, I'm not really sure what "internal things" you were hoping to understand. Serialization uses reflection to walk through the public and private fields of objects, converting them to a stream of bytes, which are ultimately written out to a data stream. During deserialization, the inverse happens: a stream of bytes is read in from the data stream, which is used to synthesize an exact replicate of the object, along with type information. All of the fields in the object have the same values that they held before; the constructor is not called when an object is deserialized. The easiest way to think about it is that you're simply taking a snapshot-in-place of the object, that you can restore to its original state at will.
The class that is responsible for the actual serialization and deserialization is called a formatter (it always inherits from the IFormatter interface). It's job is to generate an "object graph", which is a generalized tree containing the object that is being serialized/deserialized as its root. As mentioned above, the formatter uses reflection to walk through this object graph, serializing/deserializing all object references contained by that object. The formatter is also intelligent enough to know not to serialize any object in the graph more than once. If two object references actually point to the same object, this will be detected and that object will only be serialized once. This and other logic prevents entering an infinite loop.
Of course, it's easy to have a good general understanding of how this process works. It's much harder to actually write the code that implements it yourself. Fortunately, that's already been done for you. Part of the point of the .NET Framework is that all this complicated serialization logic is built in, leaving you free from worrying about it. I don't claim to understand all of it myself, and you certainly don't need to either to take full advantage of the functionality it offers. Years of writing all that code by hand are finally over. You should be rejoicing, rather than worrying about implementation details. :-)
Firstly, object A's type must be tagged with the [Serializable] attribute. Serializing A will serialize all its member data, private or public, provided the members' types are also tagged with [Serializable] (or to use your example, provided that B and C's types are marked [Serializable]). Attempts to serialize data, directly or indirectly, of a type that is not [Serializable] will result in an exception.
A number of the built-in .NET types are already marked as [Serializable], including System.Int32 (int), System.Boolean (bool), etc.
You can read more about .NET serialization here: http://msdn.microsoft.com/en-us/library/4abbf6k0.aspx.
The objects referred by the main object has to be [Serializable] as well. Providing so all is done automatically by the formatter.

Resources