When an object is serialized (by remoting to be sent across the wire) does the instance method code get serialized? Or are just the class level instance fields serialized?
I am asking this as some of my objects have large method and want to know wheather I should be using DTO's (data transfer objects) for sending data across the wire.
I guessing it's just the data plus some type version data ... am I right?
Thanks
Methods are never serialized.
Re "fields" - it all depends on the serializer; BinaryFormatter will do fields; you mention "remoting", which suggests BinaryFormatter, but remoting is largely a hangover now - from MSDN (on remoting):
This topic is specific to a legacy
technology that is retained for
backward compatibility with existing
applications and is not recommended
for new development. Distributed
applications should now be developed
using the Windows Communication
Foundation (WCF).
If you use web-services or WCF: XmlSerializer does public fields+properties; DataContractSerializer will do marked fields, etc.
Regular classes are often reusable as DTOs, but if you need lots of control over the wire (or have versioning issues), a separate DTO can be helpful.
(edit/additional) note also that there are other reasons not to like BinaryFormatter - it can be very brittle with versioning, and very painful to fix (although achievable). Other (more tolerant) serializers exist if this is likely to be an issue... if so, let me know and I'll update.
What gets saved is the data plus tags corresponding to your class and property names. The code itself doesn't get serialized.
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.
The .NET Framework ships with System.Runtime.Serialization.Json.DataContractJsonSerializer and System.Web.Script.Serialization.JavaScriptSerializer, both of which de/serialize JSON. How do I know when to choose one of these types over the other? MSDN doesn't make it clear what their relative advantages are.
We have several projects that consume or emit JSON, and the class selected for each thus far has depended on the opinion of the primary dev on each project. Some are simple, two have complex logic regarding producing managed types from JSON (the types do not map closely to the streams) but don't have any emphasis on speed, one requires speed. None interact with WCF, at least as of now.
While I'm interested in alternative libraries, I am hoping that somebody might have an answer to my question too.
The DataContractJsonSerializer is intended for use with WCF client applications where the serialized types are typically POCO classes with the DataContract attribute applied to them. No DataContract, no serialization. The mapping mechanism of WCF makes the sending and receiving very simple, but only if your platform is homogeneous. If you start mixing in different toolsets, your program might go sideways.
The JavaScriptSerializer can serialize any type, including anonymous types (one way), and does so in a more conformant way. You lose the "automagic" of WCF, but you gain more integration options.
As you can see by the comments, there are a lot of options out there for AJAX serialization, and to address your speed vs. maintainability questions, it might be worth investigating them to find a solution that meets the needs of all the teams, to reduce maintainability issues in the long term as everybody does things their own way.
2014-04-07 UPDATE:
I suggest using JSON.NET if you can. See http://james.newtonking.com/json Feature Comparison for a review of the 3 libraries considered in this question.
2015-05-26 UPDATE:
If your company requires the use of commercially licensable products, or you need every last bit of performance, you may also want to check out https://servicestack.net/.
Both do approximately the same but using very different infrastructure thus applying different restrictions on the classes you want to serialize/deserialize and providing different degree of flexibility in tuning the serialization/deserialization process.
For DataContractJsonSerializer you must mark all classes you want to serialize using DataContract atrtibute and all members using DataMember attribute. As well as if some of you classes have enum members, then the enums also must be marked as DataContract and each enum member - with EnumMember attribute.
Also DataContractJsonSerializer allows you fine control over the whole process of serialization/deserialization by altering types resolution logic and replacing the types you serialize with surrogates.
For JavaScriptSerializer you must provide parameterless constructor if you plan on deserializing objects from json string.
For me, I usually use JavaScriptSerializer in presentation logic, where there's a simple model I want to render in Json together with page, without additional ajax requests. And I even usually don't have to deserialize them back to c# - so there's no overhead at all. But if it's persistence logic, where I want to save objects into a data store (usually no-sql storage), to load them later, I prefer using DataContractJsonSerializer because the overhead of putting attributes is worth of flexibility in the serialization/deserialization process tuning, especially when it comes to loading of serialized data into the objects of the newer version, with updated definitions
Personally, I think that DataContractJsonSerializer reeks of over-engineering. I'd skip it and go with JavaScriptSerializer. In the event where JavaScriptSerializer isn't available, you can use FridayThe13th (a library I wrote ;p).
I have a desktop C# app that I want to split into two parts - server part and client part. My app is already split into two very independent parts that communicate by exchanging some (complex!) objects.
If I want to put one part of my app on some web server, what kind of technology should I use for passing those custom complex objects between the server part and client part? I was thinking about WCF, but...I'm not sure that WCF can easily handle (send/receive) custom objects (composed by many other custom objects). I don't need WCF because I'm not planning to offer my service to any third-party, I'm not planning to port my client app to other OS...
That's why I'm confused and need your help: what kind of remoting technology should I use in my case?
WCF stands for Windows Communication Foundation. In other words its about general cross process/machine communication and not limited to hetrogenous systems
One thing to remember about WCF is, despite appearances, you are not actually passing objects at all - the objects are used by a serializer to generate messages.At the other end it will deserialize into an independent copy. You don't, unlike COM, get a reference back to an object on the sender.
The reason this is important is because if the complex objects have non-serializable state such as a socket connection then this won't make it to the receiver side
Also, with the DataContractSerializer (which is the default) unless your objects are annotated with the [Serializable] attribute or you annotate the classes with [DataContract] and [DataMember] you will only be sending state that is exposed publicly (via a public field or a property).
This isn't purely a problem for WCF; Remoting requires objects derive from MarshalByRefObject or are annotated with the [Serializable] attribute. Building distributed systems is quite different from building systems that all share the same memory address space. You have to think carefully how you define that boundary between the distributed pieces because, for example, lots of small calls will kill your performance rather than few data rich calls (although from your description this might not be an issue that affects you)
So WCF can handle arbitrarily complex object graphs but just remember the above points about serialization
Well, DataContracts in WCF support complex objects, so I don't see a problem with that (how complex are your objects); however you should probably use the technology that is sufficient in your case. You can use Remoting, hell, even Sockets; but it is in almost all cases overkill and going too low in .NET stack for nothing; you will just be wasting your time in implementation.
If you have no reason against WCF, I would go that way, because it is very simple and powerful. There are also standard ASP.NET ASMX web services if you'd like.
One thing to note, whichever the technology, you should have your code structured in a distribution layer, exposing coarse-grained methods.
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.
I serialize some configuration objects and store the result bytes within a database.
new BinaryFormatter().Serialize(memoryStream, instance);
Convert.ToBase64String(memoryStream.ToArray());
These objects will be deserialized later.
new BinaryFormatter().Deserialize(memoryStream);
It's possible, that the Application has some new assembly versions at the time of deserialization. In general it works well, but sometimes I get a file load exception:
"The located assembly's manifest definition does not match the assembly reference.". The assemblies work all with strong naming, can that be the problem and how could I avoid this problem?
Thanks for help
Absolutely, using BinaryFormatter with database (i.e. long-term) storage is a bad idea; BinaryFormatter has two three big faults (by default):
it includes type metadata (shucks if you move/rename your types... this can mean strong name/versioning too)
it includes field names (fields are private details!)
it is .NET specific (which is a pain if you ever want to use anything else)
My blog post here raises two specific issues with this - obfuscation and automatically implemented properties... I won't repeat the text here, but you may find it interesting.
I recommend the use of a contract based serialization. XmlSerializer or DataContractSerializer would suffice normally. If you want small efficient binary, then protobuf-net might be of interest. Unlike BinaryFormatter, the binary from this is portable between implementations, extensible (for new fields), etc. And it is quicker and smaller, too.
I think WCF might be your best bet. It can handle passing unknown fields through to it's consumer even if it doesn't know how to deserialize them.
Example:
Service A: Knows about version 2 of the Widget class which has a Description field
Service B: Knows about version 1 of the Widget class which doesn't have a Description field
Service C: Knows about version 2 of the Widget class which has a Description field
If service A calls service B passing a Widget object and then service B calls service C passing on the same Widget object then service C will get the Description field as it was passed from service A. Service B won't have any Description field but when it deserializes it and re-serializes it it will just pass the Description field through without knowing what it is.
So, you could use WCF services with in-proc communication.
See this link for more on versioning wcf contracts.