从内存而不是磁盘加载.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.