简体   繁体   中英

Deserialization problem in .NET

I created a binary serialized file of my object, so that I could use it as a database file for many other projects. It works quite fine with the same project, but when I try to deserialize that file from other projects, it won't. The error that appears says, "xxxx.xxxx assembly not found". So, how should I serialize the object in order to make it assembly independent???

Here's my code :

            // Binary formatter
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("BinarySerialization.bin",
                                     FileMode.Create,
                                     FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, words);
            stream.Close();

What amendments do I need to do??? Please provide me with a working code example/sample.

Thanks.

BinaryFormatter is a type-based serialized; it deeply embeds type metadata into the output. I would wager that you have copied the class definition between the projects - that isn't enough for BinaryFormatter , since that is no longer the same Type (types are bound to their assembly ).

In your scenario, it sounds to me that the correct thing to do here would be to use a contract -based serializer; for example:

  • xml ( XmlSerializer , DataContractSerializer , etc)
  • json ( JavascriptSerializer , JSON.net, etc)
  • binary (protobuf-net, etc)

There would would entirely in your scenario, and would also have much better version tolerance ( BinaryFormatter is very brittle with versions)

You mention "XMLs aren't safe here, as I don't want the users to know the contents of the main database file." - in that case protobuf-net has the "advantage" of being not human-readable, but note: none of these, nor BinaryFormatter are encrypted ; if I wanted to, I could obtain the contents if I really, really wanted to. If you need strong security, use proper encryption. In which case your code becomes (in addition to maybe a few marker attributes):

using(var stream = new FileStream("BinarySerialization.bin", FileMode.Create,
                                 FileAccess.Write, FileShare.None))
{
    Serializer.Serialize(stream, words);
}

Edit to show (per comments) how to serialize Dictionary<string, List<Word>> where Word is a class with 2 string members (most of the code here is just plumbing to show a complete example):

using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;
[ProtoContract]
public class Word {
    [ProtoMember(1)]
    public string Foo { get; set; }    
    [ProtoMember(2)]
    public string Bar { get; set; }
}
static class Program {
    public static void Main() {
        var data = new Dictionary<string, List<Word>>{
            {"abc", new List<Word> {
                new Word { Foo = "def", Bar = "ghi"},
                new Word { Foo = "jkl", Bar = "mno"}
            }},
            {"pqr", new List<Word> {
                new Word {Foo = "stu", Bar = "vwx"}
            }}
        };
        using(var file = File.Create("my.bin")) {
            Serializer.Serialize(file, data);
        }
        Dictionary<string, List<Word>> clone;
        using(var file = File.OpenRead("my.bin")) {
            clone = Serializer.Deserialize<
                 Dictionary<string, List<Word>>>(file);
        }
        foreach(var pair in clone) {
            Console.WriteLine(pair.Key);
            foreach(var word in pair.Value){
                Console.WriteLine("\t{0} | {1}", word.Foo, word.Bar);
            }
        }    
    }
}

I would put all my models that have to be serialized into a seperate assembly. Then you reference this assembly everywhere you need to deserialize the Models.

If not you need some kind of generator, that recreates the models based on some schema (same as WCF does with its utilities) or use plain formats like XML to persist your data.

The serialization mechanism in .NET creates a helper dll out of the type to serialize and deserialize your data in runtime. First it will spit out a code file that gets compiled and then the helper dll is loaded to do the serialization and deserialization.

If for some reason something happens while the helper .dll gets created - let's say a compilation error- then the runtime will not found this dll.

If the dll name in your case is some random character then I would say you are facing the problem described above. You can troubleshoot this by switching on an undocument switch. See the following article:

HOW TO: Debug into a .NET XmlSerializer Generated Assembly

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM