14

我想通过以下方式加载程序集

var loadedAssembly = Assembly.Load(File.ContentsAsBytes);

File.ContentAsBytesbyte[]通过以下方式将 dll 作为 a 返回

System.IO.File.ReadAllBytes("dll location");

问题是加载的程序集 ( loadedAssembly) 丢失了它的物理位置

  • loadAssembly.CodeBase - 设置为正在加载它的程序集(这是不正确的)
  • loadAssembly.Location - 为空

有没有办法从 a 加载byte[]并获得类似的结果,Assembly.LoadFile因为我需要结果才能使用AppDomain.CurrentDomain.AssemblyResolve

4

3 回答 3

5

字节数组byte[]只是内存中的字节流。它与任何文件都没有关联。该字节数组可能是从文件中读取的、从 Web 服务器下载的或由随机数生成器自发创建的。没有“与之相伴”的额外数据。

如果要维护最初读取字节数组的文件位置,则必须在另一个变量中单独维护该数据。没有办法将额外的数据“附加”到byte[]变量上。

当您使用Assembly.Load将字节数组作为程序集加载时,它无法知道该字节数组的来源,因为没有向Load函数提供额外的数据。

作为一种解决方法,有没有一种方法可以将字节数组保存到临时文件中,用于Assembly.LoadFile为您提供所需的数据并将Location回链接到原始字节数组?

于 2013-05-23T03:43:31.280 回答
3

当然,你会认为Location 会有一个你可以访问的 set 方法或其他方式来调整它。它没有。发生的情况(我将 mscorlib.dll 放到 IL DASM 中)是,当您从文件加载时,有一个与 RuntimeAssembly 类中的程序集相关联的本机句柄。当您调用 Location getter 时,它会抓取此句柄并从本机句柄中为您提供位置,但前提是有一个。没有把手,没有位置。

这是IL:

.method public hidebysig specialname virtual 
    instance string  get_Location() cil managed
{
  .custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       37 (0x25)
  .maxstack  3
  .locals init (string V_0)
  IL_0000:  ldnull
  IL_0001:  stloc.0
  IL_0002:  ldarg.0
  IL_0003:  call       instance class System.Reflection.RuntimeAssembly System.Reflection.RuntimeAssembly::GetNativeHandle()
  IL_0008:  ldloca.s   V_0
  IL_000a:  call       valuetype System.Runtime.CompilerServices.StringHandleOnStack System.Runtime.CompilerServices.JitHelpers::GetStringHandleOnStack(string&)
  IL_000f:  call       void System.Reflection.RuntimeAssembly::GetLocation(class System.Reflection.RuntimeAssembly,
                                                                       valuetype System.Runtime.CompilerServices.StringHandleOnStack)
  IL_0014:  ldloc.0
  IL_0015:  brfalse.s  IL_0023
  IL_0017:  ldc.i4.8
  IL_0018:  ldloc.0
  IL_0019:  newobj     instance void System.Security.Permissions.FileIOPermission::.ctor(valuetype System.Security.Permissions.FileIOPermissionAccess,
                                                                                     string)
  IL_001e:  call       instance void System.Security.CodeAccessPermission::Demand()
  IL_0023:  ldloc.0
  IL_0024:  ret
} // end of method RuntimeAssembly::get_Location
于 2013-05-23T13:28:00.507 回答
2

一旦您将 传递byte[]给该Assembly.Load方法,该字节数组就绝对没有任何信息来暗示Load它来自何处的方法 - 它只是一堆字节。如果您将文件复制到单独的位置,则同样适用:

File.Copy(dllLocation, anotherLocation);
var asm = Assembly.LoadFile(anotherLocation);

装配位置将指向anotherLocation,即使装配最初是打开的dllLocation。同样,当您加载程序集字节(实质上是将程序集从磁盘复制到内存)时,这些字节的“位置”现在是内存。

于 2013-05-16T20:55:20.077 回答