【问题标题】:how to serialize/deserialize an assembly object to and from a byte array如何在字节数组中序列化/反序列化程序集对象
【发布时间】:2011-10-02 22:58:54
【问题描述】:

假设通过以下方式在内存中创建一个(可执行的)程序集 编译代码字符串。然后我想序列化这个程序集 对象转换为字节数组,然后将其存储在数据库中。然后稍后 我想从数据库中检索字节数组并反序列化 字节数组返回到一个程序集对象,然后调用该条目 集合点。

起初我只是尝试像在 .net 中的任何其他简单对象一样进行此序列化,但显然这不适用于程序集对象。程序集对象包含一个名为 GetObjectData 的方法,该方法获取重新实例化程序集所需的序列化数据。因此,对于如何将所有这些拼凑到我的场景中,我有些困惑。

答案只需要说明如何获取一个程序集对象,将其转换为字节数组,再将其转换回程序集,然后在反序列化的程序集上执行入口方法。

【问题讨论】:

    标签: c# serialization deserialization system.reflection


    【解决方案1】:

    使用反射获取程序集字节的肮脏技巧:

      MethodInfo methodGetRawBytes = assembly.GetType().GetMethod("GetRawBytes", BindingFlags.Instance | BindingFlags.NonPublic);
      object o = methodGetRawBytes.Invoke(assembly, null);
      
      byte[] assemblyBytes = (byte[])o;
    

    说明:至少在我的示例中(程序集是从字节数组加载的),程序集实例的类型为“System.Reflection.RuntimeAssembly”。这是一个内部类,因此只能使用反射来访问它。 “RuntimeAssembly”有一个方法“GetRawBytes”,它返回汇编字节。

    【讨论】:

    【解决方案2】:

    程序集更方便地表示为二进制 dll 文件。如果您那样考虑,剩下的问题就烟消云散了。特别是,查看Assembly.Load(byte[])加载来自二进制文件的Assembly。要将其写入为二进制文件,请使用CompileAssemblyFromSource 并查看结果的PathToAssembly - 然后File.ReadAllBytes(path) 以从文件中获取二进制文件。

    【讨论】:

    • 但是如果你完全在内存中进行编译呢?
    • @Beaker 那么这很痛苦;p 我在那里没有立即的答案,除了“在这里编译到临时文件夹会更容易”
    • 如果一周内没有人想出内存中的答案,那么我会将此标记为答案。
    【解决方案3】:

    System.Reflection.AssemblyISerializable 并且可以像这样简单地序列化:

    Assembly asm = Assembly.GetExecutingAssembly();
    BinaryFormatter formatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream();
    formatter.Serialize(stream, asm);
    

    反序列化同样简单,但请改为调用BinaryFormatter.Deserialize

    【讨论】:

    • 反序列化它不会产生相同的程序集...换句话说,您创建的内存流的大小不等于程序集文件的大小。
    • @TonoNam 可能不是,但他们专门询问了如何序列化对象,这将做。这并不一定意味着它将是程序员所期望的。虽然我想测试和验证你的陈述,但我认为它应该产生一个功能相同的程序集。
    • System.Reflection.Assembly 实现 System.Runtime.Serialization.ISerializable 接口,并在其 GetObjectData 方法中序列化其 FullName 属性。反序列化时,它会从其 FullName 加载程序集,因此它可以在对 appdomain 已知的程序集进行序列化和反序列化时工作,但它不是“序列化程序集解决方案”。referencesource.microsoft.com/#mscorlib/system/reflection/…
    【解决方案4】:

    这是我的例子:

    public static byte[] SerializeAssembly()
    {
      var compilerOptions = new Dictionary<string, string> { { "CompilerVersion", "v4.0" } };
      CSharpCodeProvider provider = new CSharpCodeProvider(compilerOptions);
    
      CompilerParameters parameters = new CompilerParameters()
      {
        GenerateExecutable = false,
        GenerateInMemory = false,
        OutputAssembly = "Examples.dll",
        IncludeDebugInformation = false,
      };
      parameters.ReferencedAssemblies.Add("System.dll");
    
      ICodeCompiler compiler = provider.CreateCompiler();
      CompilerResults results = compiler.CompileAssemblyFromSource(parameters, StringClassFile());
    
      return File.ReadAllBytes(results.CompiledAssembly.Location);
    }
    
    private static Assembly DeserializeAssembyl(object fromDataReader)
    {
      byte[] arr = (byte[])fromDataReader;
      return Assembly.Load(arr);
    }
    
    
    
    private string StringClassFile()
        {
          return "using System;" +
          "using System.IO;" +
          "using System.Threading;" +
          "namespace Examples" +
          "{" +
          " public class FileCreator" +
          " {" +
          "     private string FolderPath { get; set; }" +
          "     public FileCreator(string folderPath)" +
          "     {" +
          "         this.FolderPath = folderPath;" +
          "     }" +
          "     public void CreateFile(Guid name)" +
          "     {" +
          "         string fileName = string.Format(\"{0}.txt\", name.ToString());" +
          "         string path = Path.Combine(this.FolderPath, fileName);" +
          "         if (!File.Exists(path))" +
          "         {" +
          "             using (StreamWriter sw = File.CreateText(path))" +
          "             {" +
          "                 sw.WriteLine(\"file: {0}\", fileName);" +
          "                 sw.WriteLine(\"Created from thread id: {0}\", Thread.CurrentThread.ManagedThreadId);" +
          "             }" +
          "         }" +
          "         else" +
          "         {" +
          "             throw new Exception(string.Format(\"duplicated file found {0}\", fileName));" +
          "         }" +
          "     }" +
          " }" +
          "}";
        }
    

    【讨论】:

      猜你喜欢
      • 2012-03-09
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 2015-08-10
      相关资源
      最近更新 更多