BinaryFormatter.Deserialize “unable to find assembly” after ILMerge

前端 未结 10 1101
囚心锁ツ
囚心锁ツ 2020-12-14 20:53

I have a C# solution with a referenced dll (also C# with the same .Net version). When I build the solution and run the resulting exe, without merging the exe and the refere

10条回答
  •  余生分开走
    2020-12-14 21:25

    SerializationBinder was also my solution. But I have the class in a DLL which is referenced. So i have to search in all load assemblies. I have modified the answers bevor with the parameter if the binder should search in dlls.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace ibKastl.Helper
    {
       public static class BinaryFormatterHelper
       {
          public static T Read(string filename, Assembly currentAssembly)
          {
             T retunValue;
             FileStream fileStream = new FileStream(filename, FileMode.Open);
    
             try
             {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Binder = new SearchAssembliesBinder(currentAssembly,true);            
                retunValue = (T)binaryFormatter.Deserialize(fileStream);
             }
             finally
             {
                fileStream.Close();
             }
    
             return retunValue;
          }
    
          public static void Write(T obj, string filename)
          {
             FileStream fileStream = new FileStream(filename, FileMode.Create);
             BinaryFormatter formatter = new BinaryFormatter();
             try
             {
                formatter.Serialize(fileStream, obj);
             }
             finally
             {
                fileStream.Close();
             }
          }
       }
    
       sealed class SearchAssembliesBinder : SerializationBinder
       {
          private readonly bool _searchInDlls;
          private readonly Assembly _currentAssembly;
    
          public SearchAssembliesBinder(Assembly currentAssembly, bool searchInDlls)
          {
             _currentAssembly = currentAssembly;
             _searchInDlls = searchInDlls;
          }
    
          public override Type BindToType(string assemblyName, string typeName)
          {
             List assemblyNames = new List();
             assemblyNames.Add(_currentAssembly.GetName()); // EXE
    
             if (_searchInDlls)
             {
                assemblyNames.AddRange(_currentAssembly.GetReferencedAssemblies()); // DLLs
             }
    
             foreach (AssemblyName an in assemblyNames)
             {
                var typeToDeserialize = GetTypeToDeserialize(typeName, an);
                if (typeToDeserialize != null)
                {
                   return typeToDeserialize; // found
                }
             }
    
             return null; // not found
          }
    
          private static Type GetTypeToDeserialize(string typeName, AssemblyName an)
          {
             string fullTypeName = string.Format("{0}, {1}", typeName, an.FullName);
             var typeToDeserialize = Type.GetType(fullTypeName);
             return typeToDeserialize;
          }
       }
    
    }
    

    Usage:

    const string FILENAME = @"MyObject.dat";
    
    // Serialize
    BinaryFormatterHelper.Write(myObject1,FILENAME);
    
    // Deserialize
    MyObject myObject2 = BinaryFormatterHelper.Read(FILENAME, Assembly.GetExecutingAssembly()); // Current Assembly where the dll is referenced
    

提交回复
热议问题