I am working on C# TCP Server-Client programming. My problem is simple but somehow i couldnt figure it out.
I have an object i would like to seriliaze this object send over socket and deserialize client side. But problem is with deserializing. I serialize object with binaryformatter. Actually i am getting the actual byte array i should. But somehow while deserializing i am getting
System.Runtime.Serialization.SerializationException: 'Multi Server,
Version=1.0.0.0, Culture=neutural, PublicTokenKey=Null' assembly could
not found.
When i try to deserialize on the server side after serializing it has no problem.
I tried to customize binder which didnt work also. I really appriciate if somebody could help me.
If I'm guessing correct, you have 2 projects - "Multi Client" and "Multi Server".
You serialize object defined in "Multi Server" and then you have a copy of that class in "Multi Client".
So you serialize an object "MultiServer.SomeClass" and then you want to make it a "MultiClient.SomeClass". This ain't gonna work.
You need to create a common dll project (let's name it "MultiCommon", where you will put your class, and reference it by both "MultiServer" and "MultiClient". In this way, you will serialize and deserialize not "MultiServer.SomeClass" but "MultiCommon.SomeClass".
It sounds like you're using BinaryFormatter, in which case frankly I think the most valuable advice would be: don't do that. The data format of BinaryFormatter is fundamentally tied to your exact implementation details, making it very hard to a: have different code at different ends (meaning: deployment is very hard and brittle - everywhere needs to change at the same time), or b: revise the implementation over time.
Frankly, I would strongly advise looking at alternative serialization tools. I'm hugely biased, but protobuf-net works very well for this type of scenario; it is still "binary" (meaning: not text), but it isn't tied to the internal implementation details. It is fast (usually much faster than BinaryFormatter), efficient (usually much less bandwidth required than BinaryFormatter), free, and is usually very easy to apply to an existing object model; it usually means going from this:
[Serializable]
public class Custom {
public int Id {get;set;}
public string Name {get;set;}
// ...etc
}
to this:
[ProtoContract] // you can keep the [Serializable] for compat if you want
public class Custom {
[ProtoMember(1)]
public int Id {get;set;}
[ProtoMember(2)]
public string Name {get;set;}
// ...etc
}
Related
Give an object similar to:
public class MyObject : IInterfaceA
{
public IEnumerable<IInterfaceB> MyList{get; set}
public MyComplexObjectX{get; set;}
public MyComplexObjectY{get; set;}
}
which may have a fairly complex graph.
Does anybody know the best means of serializing this whereby namespace changes would not be an issue on deserialization? Would Json be the way to go perhaps?
Secondly there is also a good bit of use of lists of interfaces, generics etc. Im happy to use known types with DataContractSerializer but I think I will have the issue with namespace changes then.
Performance, size of serialized object etc are not an issue for me right now.
Thanks.
I have recently tried to play around with MongoDb's serialization. Basically, I am trying to use the driver's serializer to store my models while at the same time attempting to avoid any dependencies between my well-known model classes and 10gen's MongoDb C# driver (v1.2, if it matters).
This, by itself, is no issue. What is problematic however is that there can be (dynamic) information stored for some of the objects side by side to well-known elements. I could do this by using the [BsonExtraElements] attribute, but as I said above, I am trying to avoid coupling my models to MongoDb. Model classes that can have this behaviour, implement a certain interface:
public interface IHaveMoreInformation
{
IDictionary<string, object> Extra { get; set; }
}
For this, I have tried to write a custom convention that gets registered in the convention profile at application startup:
public sealed class ExtraElementsConvention : IExtraElementsMemberConvention
{
#region Implementation of IExtraElementsMemberConvention
public string FindExtraElementsMember(Type type)
{
return typeof(IHaveMoreInformation).IsAssignableFrom(type) ? "Extra" : null;
}
#endregion
}
This is where the problem starts. The driver expects a BsonDocument property (again, I don't want to couple). I was hoping there is a way to work around this and serialize this additional information into an IDictionary<string,object> instance.
I am helpful for any ideas to achieve this.
Thanks in advance,
Manny
After looking into the driver's inner workings, I've decided to take the matter to mongoDB's issue tracking system. Until now (1.3.1), the driver seems very keen on only accepting a BsonDocument property for extra elements; this would effectively couple models to types declared by the driver, which is a bit of a pain when you decide to switch technologies.
The issue is currently being tracked here:
https://jira.mongodb.org/browse/CSHARP-395
Hopefully this improvement will find its way into 1.4 and help people looking to achieve something similar in the future.
I am working on a program, where I save it's project files by serializing Project class.
Because I am still working on it, some classes, that are part of Project class, do change from time to time (e.g. class got new property). It makes "simple" deserialization impossible.
Is there any way to solve it ? I mean, without writng custom serializer ? (which probably is something high above my level for now)
Just in case, I am using BinaryFormatter.
I hope I understood your problem correctly. You have a class serialized to a file which you have since changed in the program (e.g you have added another property). Now you want to deserialize this class from the file. This is not a problem as long as you have only added new properties. They will be ignored by the deserializer. It creates a new instance of your class (that is the reason why serializable classes have to have a default constructor) and tries to fill the properties it finds in the stream to derserialize. If you change a property's type or remove a property, you won't be able to deserialize the original file.
One workaround for removing properties is to keep them in the class, but just stop using them in the rest of the program. A workaround for properties that have been changed to a different type could look something like this:
[Serializable]
public class MyClass
{
int? newProperty;
[XmlElement("Property")]
public string OldProperty
{
get { return string.Empty; }
set
{
if (!newProperty.HasValue)
{
int temp;
if (int.TryParse(value, out temp))
{
newProperty.Value = temp;
}
}
}
}
public int NewProperty
{
get { return newPropery.HasValue ? newProperty.Value : 0; }
set { newProperty.Value = value; }
}
}
From my experience, I've found using BinaryFormatter for serialization/de-serialization of data types that are going to change a really bad idea. If something changes in your data type, from what I know the BinaryFormatter will fail in the process.
To overcome this issue in the data types I was using, I had to write my own serializer, which wasn't actually that much of a major task. You can use the BinaryReader and BinaryWriter classes to read and write the data in and out of your type. That way you can control the data you are expecting and handle any missing data either by adding default values, skipping the property altogether, or throwing some form of Exception to signify corrupt data. Refer to the MSDN article links above for more information.
With help from Merlyn Morgan-Graham's comments I've found solution, that will work for me.
Versioning described in Version Tolerant Serialization is really good idea, but when I use only [Serializable] attribute.
I forgot to write (my mistake), that I am using ISerializable interface.
I've found, that in deserialization constructor SerializationInfo object has MemberCount property, which solves my problem if I only add new properties/members from time to time. With this information, new members/properties, that can't be deserialized from older file, can be set to default or maybe I can use some prompt form.
Other way here would be using something like assembly version in deserialization, as a first deserialized member. This can solve deserialization problems with more complex class changes.
Either way, I agree with Merylin - "if you can't script something, you shouldn't be building it". ;)
I am trying to deserialize "SomeClass" with an older version of an application. I get this below exception
System.Runtime.Serialization.SerializationException: The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.
Deserialization throws exception when I serialize version 0.9 and try to deserialize using version 0.8. I thought the OptionalField attribute would do the trick, but it didn't.
// Version 0.8
[Serializable()]
class Foo{
Bar b;
}
// Version 0.9
[Serializable()]
class Foo{
Bar b;
[OptionalField]
Zoo z;
}
Given that I cannot change version 0.8, how should I add more state to Foo object such that previous versions can deserialize whatever they can?
Any pointer will be really appreciated.
Update 1
Bar and Zoo are other classes which are serializable and contains Hashtables and other serializable stuff. Everything is serializable in those classes.
Also, I don't have any struts.
First, never NEVER use the CLR's serialization functions for anything that resembles long-term storage. We make that mistake usually once, put objects in a blob database field and pat ourselves in the back thinking we're clever. And then the CLR gets a patch or our assemblies change versions and you're screwed. So don't do it.
If you still want to do it, the best way to manage the problem is to create your own SerializationBinder that looks something like this:
public sealed class CustomBinder : SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
Type typeToDeserialize = null;
if (typeName.IndexOf("SomeType") != -1) {
typeToDeserialize = typeof(Foo.Bar.Bax.NewType);
}
else if (typeName.IndexOf("SomeOtherType") != -1) {
typeToDeserialize = typeof(Foo.Bar.Bax.SomeOtherNewType);
}
else {
// ... etc
}
return typeToDeserialize;
}
}
Set the Binder property of the formatter you're using prior to deserializing so that it overrides the defaults.
Note that I'm not offering a drop-in solution here, I'm recommending how to solve the problem. Once you've converted out of whatever you're doing, investigate other serialization technologies like protobuf, or write your own. Either way you should never rely on the CLR for long-term serialization support.
If constructors for each version are compatible (e.g. there is a parameterless or Foo(Bar b) constructor for both versions) you can call
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = Formatters.FormatterAssemblyStyle.Simple;
Before deserializing your stream.
As an advisory to people investigating this issue "before it is too late"... I strongly advise against persisting via BinaryFormatter. It is OK for transient transfer between 2 app-domains that are in sync, but that is about it IMO. Other serialization tools exist that don't have these issues. In terms of binary, protobuf-net is a pretty reasonable option - allowing add/remove/rename etc without pain.
It seems that one way to do this would be to have a versioned object, that way you could try deserializing the object using the latest version. If that didn't work, step back a version until it's successful. Then once you have your object, update it to the latest version of the object and use default values for any fields you don't have data for.
The optional field attribute should have done the trick. Can you post the actual classes that you are trying to serialize.
You could try these things first -
convert structs if any to classes
try Soap Serialization instead of binary serilization
I've been using SubSonic 2 for a while now, but as I am starting a new project, I'd like to upgrade to 3. In my old project, I used a custom, non-sustainable hack to serialize things for web services. I really would like to find a more elegant solution.
I'm using Mono, so I need to stay within implemented classes, e.g. DataContractSerializer is probably out. Still on ASMX, though would love to upgrade to WCF as soon as the support is solid. Moonlight/Silverlight will be the initial clients. JSON/protobuf in the future...
The standard Xml serializer is opt-out, so I'd need some way to take control of it. Which brings me to IXmlSerializable. I'm rather unfamiliar with SS's templates, but it seems that editing these would allow me to generate the serialization code necessary to not touch the rest of the hierarchy chain. Is this a "good idea"?
I'd love to just use SS's POCO support, but I don't think it supports complex types or arrays.
Other thoughts/options?
IXmlSerializable is IMO more than a little awkward to get right. Note that if you are handling the XmlSerializer code yourself you can override everything at runtime by using the constructor that accepts XmlAttributeOverrides (but if you use this you should cache and re-use the XmlSerializer instance, or it will leak like a sieve).
You briefly mention protobuf; note that protobuf-net (even in v1) allows you to add member-level serialization data at the type level, so you can include that information in a partial class alongside a generated type:
// file 1
partial class GeneratedClass
{
public int Foo { get; set; }
public string Bar { get; set; }
}
// file 2
[ProtoPartialMember(1, "Foo")]
[ProtoPartialIgnore("Bar")]
partial class GeneratedClass {}