I currently have a socket application that I use to send string back and forth from a client to a server. I recently decided that it would make more sense to send serialized objects instead but ran into a problem. I converted the code to use the SoapFormatter which allowed me to serialize the objects to string and send the string. I ran into an issue on the client side when trying to deserialize inherited objects. It seems that the soapformatter does not support inheritance. The problem occured during deserialization, if i tried to deserialize the parent object when i send the child object (I dont know if this is correct terminology) it would throw a cast exception.
My question is, does the BinaryFormatter support inheritance??
Both SoapFormatter and BinaryFormatter support serializing objects of types that inherit from other types. In other words, both do support inheritance.
You should probably ask another question about your specific problem with SoapFormatter. Also, just using different formatter most likely won't fix your problem (but you coul've tried it before asking here).
Related
I am encountering a really weird Exception on one of my application (later referenced as ApplicationB)
`Unable to find assembly 'MsgPack, Version=0.5.0.0, Culture=neutral, PublicKeyToken=a2625990d5dc0167'.`
Here is my scenario, on my ApplicationA I have serialized an object using MsgPack and store it into Redis using SE.Redis. Later on, I query this object and deserialize it (of course still using MsgPack). Once this is done, I am sending this object via a TCP/Componennt that serializes this same object using BinaryFormatter. On the other side, ie on ApplicationB, once the packet arrived, it is deserialized using BinaryFormatter and this is where I get the exception.
I don't have any control on the TCP/Component and the serializer it uses.
So why do I get this error on ApplicationB which should know any thing about MsgPack?
Just a thought I want to share, it seems that MsgPack create on the fly DataContract and when deserializing, it might applies some attributes on the object that conflict with the BinaryFormatter. Of course I am not sure about that.
But has anyone encountered this problem?
Cheers.
EDIT: I noticed that for member of type object, MsgPack adds a lot of members for defining the type store in the object member (like IsDictionary, IsList, etc.). Does it impact BinaryFormatter?
When using binary serialization, only the fully qualified type name and its data is serialized to a byte-array. The serializer on the other side wants to deserialize its data. It first reads the type name from the byte-array and tries to find and instanciate that type. That type must be somewhere in a DLL. So it looks for the given DLL (in your case MsgPack) but it cannot be found. Thus: Make sure the DLL MsgPack is located on both sides.
If it is not possible to to have the DLL on the other side, your could try to serialize the DLL itself and send it over to the other side. First deserialize the DLL, put it inside your bin folder or load it into memory, then deserialize the type with its data. But you must really, really, really make sure if you wanna do that. I wouldn't.
Have you ever considered communicating between AppA en AppB using WCF?
Is it possible to Serialize a class in C++ and deserialize it to a similar class in C# using protocol buffer? I have tried Json serialization to overcome this serialization issue in different platforms but it has issues on some data types such as array list, etc. So any advice on using google's protocol buffer?
Protocol Buffers will allow you to describe a data structure, and serialize/deserialize that to objects in C++, Java, C# and other platforms. You don't (generally, anyway) get to serialize instances of your own classes - you serialize instances of the generated classes. (I know that protobuf-net allows you to decorate your own classes with attributes describing how to serialize them to protocol buffers, rather than having to use generated classes. I don't know if that has been done in C++.)
It's not clear whether that really meets your requirements, but protobufs certainly allow for cross-platform data exchange. It does have limitations in terms of what data can be serialized - it's all reasonably primitive, and you build up more complex structures from the primitive ones. That can be frustrating if you've already got your data model in code, and then have to reimplement it in protocol buffers, but it does work...
I have a pretty complex web of objects I'd like to serialize and deserialize in an untrusted environment (web browser, using Unity 3D). Plain BinaryFormatter serialization is working fine, but deserialization crashes with "access to private field" errors. It works perfectly when I am running locally.
I would rather not make my codebase suck by making all my private fields public. What is the best way to get deserialization to work in an untrusted environment without doing this? I am open to changing serialization methods, BinaryFormatter was just the easiest to get started with.
UPDATE I don't want to prevent serialization from accessing my private data, I want to allow serialization to access my private data without having to make it public, compromising the encapsulation of my code.
Thanks.
Serializers like XmlSerializer and JavaScriptSerializer work against the public members, so they should (crosses fingers) work acceptably in terms of trust. You could also try protobuf-net if you want binary - but I haven't aggressively tested this scenario (it works in things like Silverlight, though, which has a fairly picky trust model).
If you want to stick with BinaryFormatter but don't want it touching your fields directly you could implement ISerializable, but doing it all manually is... painful.
None of the answers really answered my question (see the update for clarification). I ended up writing my own simple serialization format using BinaryWriter. In the end I realized what I did was equivalent to manually implementing the ISerializable interface for my classes. I had to manually implement the graph serializatoin code. While not hard, it's a bit subtle, and it has already been done for me. For future perople with this question, if there are no better answers, I recommend manually implementing ISerialzable.
Well, if you want to prevent the private field access by serialization, you may want to move over to Xml Serialization of perhaps even Json serialization.
You can prevent the private fields from serializing by placing NonSerializaed attributes on them, but you may run into problems when developers expect their fields to contain valid values and do not take into account the fact that those field values get lost when transferred to the Unity plugin.
.NET provides the JavaScriptSerializer class in the
System.Web.Script.Serialization namespace. (provided in System.Web.Extensions.dll)
It was originally intended to support AJAX web server apps, but the class can be used by any application (client, server, hybrid, anything) that serializes and deserializes .NET classes to JSON. I have a desktop app that captures screenshots and uploads to Facebook, and uses this class to deserialize the response.
would I ever want to look elsewhere for JSON deserialization from within .NET?
If so, why? and where would I Look?
If not, then why does JSON.Net exist? Is it strictly for historical purposes? (ie, because it was created by the community before the JavaScriptSerializer).
In my case there are various reasons that prevent me to use JavaScriptSerializer. Here are some of them.
1) Ugly deserialization when dealing with anonymous types
While the usage is fairly straight forward for serialization:
JavaScriptSerializer serializer = new JavaScriptSerializer();
String json = serializer.Serialize(data);
For deserialization however, there is a minor annoyance in that the deserializer accepts a generic type along with the content:
serializer.Deserialize<T>(String s)
this can be a problem if the type T is not known at compile time and needs to be dynamic. The work around is a bit ugly as I learnt because it uses reflection to create a generic method (but it works)
var result = typeof(JavaScriptSerializer).GetMethod("Deserialize")
.MakeGenericMethod(JsonDataType)
.Invoke(serializer, new object[] { inputContent });
Please note: according to Dave Ward comment on this answer there's a DeserializeObject() that can be used to prevent this.
2) Cannot handle circular references
I have seen this using Entity Framework, Linq to SQL, NHibernate, NetTiers and even when using Castle's proxy.
According to MS Connect the circular reference exception will be raised when a navigable relation is double-sided (can access both sides of the relation), so the first thing to do is disable one side of the relation. The exception will also be thrown when you use 1:1 relations (or 1:0..1 or any relation causing the creation of an EntityReference type property), in this case the exception will be of type System.Data.Metadata.Edm.AssociationType.
The solution to this is to make the serializer ignore the properties of type EntityReference, using an empty implementation of a class deriving from JavaScriptConverter and registering it using the RegisterConverters method of the JavaScriptSerializer object.
3) Useful features that leads to less testable code
A useful feature of the JavaScriptSerializer is that you can also implement a custom JavaScriptConverter and pass that in to JavaScriptSerializer for fine-grained control over the serialization/deserialization. However, for it to be really useful you need to know the types at compile time and have references to those types. This really limits the usefulness of this feature because by referencing those classes your code becomes tightly coupled so you cannot easily use it in something like an MVC filter.
For these reasons I have often ended up using Json.NET.
Hope this helps!
I use the JavaScriptSerializer on a wide variety of scenarios, it never let me down, and never needed to look elsewhere for other solutions... :)
...but i do know that JSON.net has some added values like LINQ to JSON, which i never needed, and nice JSON formatting but as Serializing goes JavaScriptSerializer does the work fine.
I have a [serializable] class that I serialize using a binary formatter, send over a network (TCPListener, TCPClient) and then run deserialize on. Every time I get to deserialize I get an outofmemory exception. Does anyone know why this might be happening?
(The class I'm sending is very small)
Thanks,
PM
EDIT: My class is a linked list of one of my other classes, and some methods. I made both Serializable.
Does the class have a serialization constructor (one that takes the SerializationInfo and StreamingContext params)? If so, might there be a bug in the serialization constructor?
(Please provide more details on the class in question.)
Sometimes the serializer and/or deserializer have trouble with cyclic references.
I'd recommend custom serializers & deserializers anyway. It really is beneficial to be able to look at just your code and know what the storage format looks like.