.NET Forum / Languages / C# / January 2008
serialization question
|
|
Thread rating:  |
DBC User - 10 Jan 2008 15:50 GMT I have a binary serialized file on the client box. I would like to open it with a completly different program to see what is in it. I copied the the serialized class information from the project which created it to a new project which will open the serialzed object. When the program ran I got a run time error stating, I will not be able to open the serialized object since it was created by a different dll or namespace. Is it possible to do this? Thanks.
Kevin Spencer - 10 Jan 2008 16:05 GMT Sure. Put the serializable class and the serializer class into a class library, and use that in both projects.
 Signature HTH,
Kevin Spencer Chicken Salad Surgeon Microsoft MVP
>I have a binary serialized file on the client box. I would like to > open it with a completly different program to see what is in it. I [quoted text clipped - 5 lines] > Is it possible to do this? > Thanks. Nicholas Paldino [.NET/C# MVP] - 10 Jan 2008 16:22 GMT That's not going to work, since that serialization engine is going to look at the type of the object that is serialized.
By moving the class file to another assembly, you are effectively creating two separate types, and serialization will fail.
You could do this and create a ISurrogateSelector implementation which will select the correct types to serialize/deserialize.
However, the easy way to do this would be to separate the class into a separate assembly, and then reference the assembly from both programs. This way, you have ^one^ definition of the type.
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
> Sure. Put the serializable class and the serializer class into a class > library, and use that in both projects. [quoted text clipped - 8 lines] >> Is it possible to do this? >> Thanks. Peter Duniho - 10 Jan 2008 19:26 GMT > [...] > However, the easy way to do this would be to separate the class into > a > separate assembly, and then reference the assembly from both programs. > This > way, you have ^one^ definition of the type. This is, as near as I can tell, what Kevin meant when he wrote "into a class library".
I didn't read his post to mean copying the code for the serialized class into each place it will be used, but rather to move it into a separate assembly just as you've suggested here.
Pete
Nicholas Paldino [.NET/C# MVP] - 10 Jan 2008 20:11 GMT Yeah, I read it too fast, I read it as putting the class in each assembly.
- Nick
>> [...] >> However, the easy way to do this would be to separate the class into [quoted text clipped - 11 lines] > > Pete DBC User - 10 Jan 2008 20:24 GMT On Jan 10, 2:11 pm, "Nicholas Paldino [.NET/C# MVP]" <m...@spam.guard.caspershouse.com> wrote:
> Yeah, I read it too fast, I read it as putting the class in each > assembly. [quoted text clipped - 18 lines] > > - Show quoted text - Thanks all for the answer. In this 'particular' situation I need a way to read it without mixing and creating a dll/lib to use it. Sorry. This is a very peculiar situation. Hopefully as suggested ISurrogateSelector might help me. I never used it. I need to google it to find out more about it. If any one has any sample code, please let me know otherwise thank you for the comments and suggestions.
Nicholas Paldino [.NET/C# MVP] - 10 Jan 2008 20:32 GMT I have to ask, why can't you use a separate assembly dll? It seems like a silly requirement.
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
On Jan 10, 2:11 pm, "Nicholas Paldino [.NET/C# MVP]" <m...@spam.guard.caspershouse.com> wrote:
> Yeah, I read it too fast, I read it as putting the class in each > assembly. [quoted text clipped - 25 lines] > > - Show quoted text - Thanks all for the answer. In this 'particular' situation I need a way to read it without mixing and creating a dll/lib to use it. Sorry. This is a very peculiar situation. Hopefully as suggested ISurrogateSelector might help me. I never used it. I need to google it to find out more about it. If any one has any sample code, please let me know otherwise thank you for the comments and suggestions.
Peter Duniho - 10 Jan 2008 20:41 GMT > Thanks all for the answer. In this 'particular' situation I need a way > to read it without mixing and creating a dll/lib to use it. Sorry. I agree with Nicholas...that seems like a silly requirement.
However, if that is indeed your requirement, you'll have to write your own serialization, something that's not tied to the .NET class the way the built-in is.
Pete
Marc Gravell - 10 Jan 2008 21:43 GMT One cheap option here - use xml serialization. DataContractSerializer, for example, can be used with "preserver references" enabled to properly serialize the object *graph* (not the object *tree* that XmlSerializer would produce) - just wihout the assembly information that is plaguing you. It would also be trivial to parse, transform, etc.
If you are concerned about space (for big graphs), then another easy trick is to chain a GZipStream.
An illustration (demonstrating DataContract working on a graph with loops, and working through GZipStream):
[DataContract] public class MyData { // simple values [DataMember] public int SomeValue { get; set; } [DataMember] public string SomeOtherValue { get; set; }
// to prove object graph [DataMember] public MyData Sibling { get; set; } } class Program { static void Main() { MyData a = new MyData { SomeValue = 4, SomeOtherValue = "abc" }, b = new MyData { SomeValue = 6, SomeOtherValue = "def", Sibling = a }; a.Sibling = b; // make a closed loop...
DataContractSerializer dcs = new DataContractSerializer( typeof(MyData), null, int.MaxValue, true, true, null);
// write using (Stream zip = new GZipStream( File.Create("test.bin"), CompressionMode.Compress)) { dcs.WriteObject(zip, a); zip.Close(); }
// read MyData c; using (Stream zip = new GZipStream( File.OpenRead("test.bin"), CompressionMode.Decompress)) { c = (MyData)dcs.ReadObject(zip); }
Console.WriteLine("{0}, {1}\t{2}, {3}\t{4}", c.SomeValue, c.SomeOtherValue, c.Sibling.SomeValue, c.Sibling.SomeOtherValue, ReferenceEquals(c, c.Sibling.Sibling));
} }
Marc Gravell - 10 Jan 2008 21:47 GMT I forgot to say; the point of a DataContract is that you can load it simply with a matching contract (i.e. copy/paste) - it doesn't care about specific assemblies etc.
Marc
Nicholas Paldino [.NET/C# MVP] - 10 Jan 2008 22:02 GMT And the XML will not work because the file is ^already^ serialized from another program.
Using a DataContractSerializer ^might^ work, as the DataContractSerializer does honor classes that are tagged with Serializable and follows the same semantics as it, but there is no guarantee that the format will be compatable with what the BinaryFormatter produces (as a matter of fact, I'd be very surprized if it did).
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
>I forgot to say; the point of a DataContract is that you can load it > simply with a matching contract (i.e. copy/paste) - it doesn't care > about specific assemblies etc. > > Marc Marc Gravell - 10 Jan 2008 22:13 GMT [Nicholas Paldino]> And the XML will not work because the file is ^already^ serialized from another program.
Ah - right, misunderstood. Yes, if the OP *already* has the serialized file, then, well, it gets very tricky.
My reply was to "if I am /designing/ a system that (as a requirement) must be able to do this..." - in which case a data-contract is a perfectly viable solution - but no, it absolutely won't allow you to read output from BinaryFormatter...
But then, the same applies to your own suggestion of using a shared assembly from both projects - it is presumably already too late to change the one that produced the existing file.
Marc
DBC User - 11 Jan 2008 03:21 GMT > [Nicholas Paldino]> And the XML will not work because the file is > ^already^ serialized from another program. [quoted text clipped - 12 lines] > > Marc Thank you very much again. Since you have asked the requirement, here is what is happening. We have a massive project which does all these work and I do have these serialised object in a seperate dll. Now I got a special request from one of a biggest client, they want to update this serialised object in all their install with specific information. I do have an option on the GUI to update the serialised object. But client said, users tend to make mistake and the IT department want to update it through back door, by asking all the users in the company to run a program from network and 'this' program will read the clients serialised object and update it. So here is what I went about, I created a program referenced the dll to update the object and everything worked ok. I signed the application with the certificate and ran a test in one of our server, dll failed with security exception stating the dll doesn't have enough security and has to be given full trust. Now I ran a caspol on it manually and it worked. I could have added the caspol command in a batch program and let the client run the batch program, where the caspol runs first then run the actual program. But the server location where I need to point to the dll can not be hardcoded since there are multiple server location the clients could point to. So I thought, if somehow I can access the serialised object through the main program instead of the dll I could resolve the problem without running caspol. This is my story :(
Bilz - 11 Jan 2008 14:57 GMT > This is my story :( Assuming you already have the serialized file but you don't have access to the DLL that created it, your only real option is to write a tool that parses the binary file directly! Yuck.
I have written a similar tool in the past... I HACKED the binary file to change the values by using the BinaryReader and BinaryWriter class.
I hate this type of code... I despise it, really... but sometimes it is the only way.
B
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|