Run CMD
Run CMD

Reputation: 3035

Serialization problem

We save and read files by (de) serializing a class named "DocumentClass". All was working well, untill we added 2 more fields to the documentclass. (We think that's the problem)

When we now try to open files that were serialized by the previous edition, we get an error.

System.ArgumentException: Object of type 'System.Int32' cannot be converted to type 'System.String'. at SoftwareProject.Componenten.Bestand.DocumentClass.d(String A_0) at de..ctor(String A_0) at g.a(String A_0)

The method generating the error is the method "Read". (DocumentClass.d() is the obfuscated name )

But things get weirder: when we open the file in VS debug mode, no error is generated, but all fields in the documentclass are 0 or null ???

We are lost here ... please help ... We've added the [OptionalField] attribute to the new fields, but that doesn't help ..

Why are all values null in debug mode ?? And where is the runtime error coming from ? How can we debug it ?

Thanks in advance!!

public static DocumentClass Read(string fullFilePath)
{

     DocumentClass c = new DocumentClass();
     Stream s = File.OpenRead(fullFilePath);
     BinaryFormatter b = new BinaryFormatter();
     //b.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
     b.Binder = new MyCustomBinder(); 

     try
     {
      c = (DocumentClass)b.Deserialize(s);
     }
     catch( Exception exc )
     {
      s.Close();
      throw exc;
     }
     finally
     {
      s.Close();
     }
     return c;
        }


        public class MyCustomBinder : SerializationBinder {

     public override Type BindToType(string assemblyName, string typeName) {
      Type tyType = null;
      string sShortAssemblyName = assemblyName.Split(',')[0];
      Assembly[] ayAssemblies = AppDomain.CurrentDomain.GetAssemblies();
      if (sShortAssemblyName.ToLower() == "debugAssemblyName")
      {
       sShortAssemblyName = "AppAssemblyName";
      }
      foreach (Assembly ayAssembly in ayAssemblies) {
       if (sShortAssemblyName == ayAssembly.FullName.Split(',')[0]) {
        tyType = ayAssembly.GetType(typeName);
        break;
       }
      }
      return tyType;
     }
}

Upvotes: 2

Views: 433

Answers (3)

Jon Arnar
Jon Arnar

Reputation: 11

.Net has something called "Version Tolerant Serialization" which most likely solves this issue ;)

You should check out this easy to understand example on object serialization:

http://programming.flashadventures.com/c-sharp/writing-objects-to-files-serialization/

Upvotes: 1

bruno conde
bruno conde

Reputation: 48265

I think you need to use Custom Serialization

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1063884

I assume you are using BinaryFormatter? This serializer is notoriously brittle, since it (by default) includes the field-name in the stream; this impacts obfuscation particularly badly. Presumably the obfuscator is now choosing new named for the fields (perhaps at random, perhaps due to the new fields), and so it can't deserialize correctly.

A few options:

  • don't obfuscate the DTO
  • implement ISerializable so the field names don't matter
  • use a serializer that doesn't care about field names

I'd personally opt for the latter, but I'm a bit biased ;-p I know of people using protobuf-net with obfuscated classes; the data only includes numeric markers, so the meaning isn't really exposed (except of course, by inspection of the data - post codes etc, but that is the job of encryption).

Upvotes: 0

Related Questions