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

问题描述:

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

I am having a perplexing problem trying to load a .NET assembly from memory instead of from the disk. If I compile the assembly and then load it from disk (either using LoadFile or LoadFrom), then the application works just fine.

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

However, if I include the compiled assembly DLL file as an embedded resource in the project and then use Assembly.Load to load the bytes from the resource stream, then I get a series of random errors as the application continues to run.

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

This is only a problem on one of eight assemblies in the application - all of the others work fine from either the disk or memory.

感谢您的帮助!

你没有提供足够的细节让我猜测你的问题是什么.但是,我可以展示我使用的模式.

You have not provided enough detail for me to even guess at what your problem is. However, I can present the pattern I use.

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

The way I handle embedding dependent assemblies is to use the AssemblyResolve event. You wire up the event once and then if the CLR cannot find the assembly on disk it will raise this event. When the event is raised then you extract the assembly bits from the resource manifest and call 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;
      }
  }
}

然后就可以这样使用了.

And then it can be used like this.

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!
}

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

I have used this pattern successfully for many years. There are a few caveats, but for the most part it works well. It is certainly a lot better than using the ILMerge tool.