views:

151

answers:

3

I wrote a plugin system and I want to save/load their properties so that if the program is restarted they can continue working. I use binary serialization. The problem is they can be serialized but not deserialized. During the deserialization "Unable to find assembly" exception is thrown. How can I restore serialized data?

+2  A: 

Use the fuslogvw.exe tool to find out where the CLR is searching for the assembly.

Hans Passant
Thanks it is a very useful tool :)
Heka
+1  A: 

More than likely, your plugin assembly is not loaded at the time that you're deserializing the data. Because it's an external, plugin assembly, I'm guessing you're explicitly loading it. You are probably deserializing the properties object before loading the assembly. You can diagnose and fix the problem by hooking the AssemblyResolve and AssemblyLoad events on the current AppDomain and observing exactly when they're called.

You can also use AssemblyResolve to fix the load error by putting explicit Assembly load code in it yourself and returning the loaded assembly. I don't recommend this because it's kindof backwards.

AssemblyResolve

Kennet Belenky
Actually I call deserialization after loading the assembly.
Heka
A: 

Ok here I have found something. :)

http://techdigger.wordpress.com/2007/12/22/deserializing-data-into-a-dynamically-loaded-assembly/

I used this approach and it worked without any problem.

Firs defined a binder class:

    internal sealed class VersionConfigToNamespaceAssemblyObjectBinder : SerializationBinder {

      public override Type BindToType(string assemblyName, string typeName) {

       Type typeToDeserialize = null;

       try{

         string ToAssemblyName = assemblyName.Split(',')[0];

         Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();

         foreach (Assembly ass in Assemblies){

           if (ass.FullName.Split(',')[0] == ToAssemblyName){

               typeToDeserialize = ass.GetType(typeName);

               break;

           }

         }

       }

       catch (System.Exception exception){

         throw exception;

       }

       return typeToDeserialize;

      }

    }

And then serialization methods:

            public static byte[] Serialize(Object o){           

             MemoryStream stream = new MemoryStream();

             BinaryFormatter formatter = new BinaryFormatter();

             formatter.AssemblyFormat

                 = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

             formatter.Serialize(stream, o);

             return stream.ToArray();

            }


            public static Object BinaryDeSerialize(byte[] bytes){

              MemoryStream stream = new MemoryStream(bytes);

              BinaryFormatter formatter = new BinaryFormatter();

              formatter.AssemblyFormat 

                  = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

              formatter.Binder 

                  = new VersionConfigToNamespaceAssemblyObjectBinder();

              Object obj = (Object)formatter.Deserialize(stream);

              return obj;

            }

And I use them where I need.

            protected void SaveAsBinary(object objGraph, string fileName)

            {

              byte[] serializedData = Serialize(objGraph);

              File.WriteAllBytes(fileName, serializedData);

            }


            protected object LoadFomBinary(string fileName)

            {     

              object objGraph = null;

              try

              {

                objGraph = BinaryDeserialize(File.ReadAllBytes(fileName));

              }

              catch (FileNotFoundException fne)

              {

            #if DEBUG

                throw fne;

            #endif

              }      

              return objGraph;

            }

Thanks for help :)

Heka