从内存而不是磁盘加载.NET程序集

use*_*713 6 .net c# assembly-resolution .net-assembly

我在尝试从内存而不是从磁盘加载.NET程序集时遇到了一个令人困惑的问题.如果我编译程序集然后从磁盘加载它(使用LoadFile或LoadFrom),那么应用程序工作正常.

但是,如果我将已编译的程序集DLL文件作为嵌入式资源包含在项目中,然后使用Assembly.Load从资源流加载字节,那么随着应用程序继续运行,我会收到一系列随机错误.

这只是应用程序中八个程序集之一的问题 - 所有其他程序在磁盘或内存中都能正常工作.

谢谢您的帮助!

Bri*_*eon 15

你还没有提供足够的细节来猜测你的问题是什么.但是,我可以呈现我使用的模式.

我处理嵌入依赖程序集的方法是使用该AssemblyResolve事件.您将事件连接一次然后如果CLR在磁盘上找不到程序集,它将引发此事件.引发事件时,从资源清单中提取汇编位并调用Assembly.Load.

这是代码的样子.

internal class AssemblyResolver
{
  public static void Register()
  {
    AppDomain.CurrentDomain.AssemblyResolve +=
      (sender, args) =>
      {
        var an = new AssemblyName(args.Name);
        if (an.Name == "YourAssembly")
        {
          string resourcepath = "YourNamespace.YourAssembly.dll";
          Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcepath);
          if (stream != null)
          {
            using (stream)
            {
              byte[] data = new byte[stream.Length];
              stream.Read(data, 0, data.Length);
              return Assembly.Load(data);
            }
          }
        }
        return null;
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后就可以像这样使用它.

public static void Main()
{
  // Do not use any types from the dependent assembly yet.

  AssemblyResolver.Register();

  // Now you can use types from the dependent assembly!
}
Run Code Online (Sandbox Code Playgroud)

我已成功使用这种模式多年.有一些警告,但在大多数情况下它运作良好.它肯定比使用ILMerge工具好很多.