C# 如何在不使用assembly.load的情况下加载程序集?
是否可以通过将程序集流式传输到内存中来实现这一点?如果是这样的话,如何做到这一点 原因:C# 如何在不使用assembly.load的情况下加载程序集?,c#,.net,reflection,assemblies,C#,.net,Reflection,Assemblies,是否可以通过将程序集流式传输到内存中来实现这一点?如果是这样的话,如何做到这一点 原因: 我不想锁定加载的dll。我希望能够动态加载、更改代码、编译并再次重新加载它据我所知,您需要执行以下操作: 将程序集从磁盘加载到内存中,以便使用其中的数据或调用其中的代码 以后可以卸载程序集 避免在磁盘上锁定程序集,这样您就可以在不退出应用程序(或先卸载程序集)的情况下对其进行修改 基本上,您所描述的是一个插件系统,您可以通过使用阴影dll和应用程序域来实现这一点 首先,为了在不退出应用程序的情况下卸载程序集
我不想锁定加载的dll。我希望能够动态加载、更改代码、编译并再次重新加载它据我所知,您需要执行以下操作:
Assembly.Load
的重载,如果有多个程序集要加载和替换,则可以从字节数组加载程序集
例如,如果您的插件程序集A.dll依赖于第二个程序集B.dll,并且您在调用assembly.load之前使用字节数组技巧将A.dll加载到内存中,则您需要在应用程序域中处理程序集解析调用(可以在需要加载程序集时通知您,并“帮助”加载过程),或者您需要确保B.dll的加载方式与A.dll的加载方式相同,否则从内存加载A.dll将自动从磁盘加载B.dll
下面是关于使用不同应用程序域的更多信息 当您创建另一个应用程序域时,通过使用.NET中的类,您正在内存中创建一个单独的分区,您可以在其中运行代码。它实际上与您的主要应用程序域是分离的,并且只有一个小孔穿过墙壁将它们隔开 通过这个洞,您可以传递消息,比如方法调用和数据 构造新的应用程序域后,将在其中加载一个或多个程序集。通常,如果要加载到其中的程序集是为这种加载类型而构建的,则加载1;如果没有,则加载2(下面将对此进行详细介绍) 加载程序集后,您可以在另一个应用程序域内构造一个或多个对象,以便第一个应用程序域可以与这些对象通信。这些对象需要从一个类中派生出来,这个类允许一些魔法发生 基本上就是这样。在另一个应用程序域中,将创建加载到该应用程序域中的类型的对象。此类型从。构造此对象的请求来自第一个应用程序域,在该应用程序域内,构造了一个代理对象,该代理对象看起来像但不是在该其他应用程序域中创建的同一对象。代理通过那个洞和另一个物体说话 现在您有了两个应用程序域和两个对象,每侧一个,这些对象相互通信 通过这种设置,以后可以断开对象之间的连接,然后卸载另一个应用程序域,这基本上会破坏该分区。然后,如果您愿意,您可以构造一个新的第二个应用程序域,然后重新开始,实际上再次从磁盘重新加载程序集 需要注意的一件事是通过这个孔的数据。如果您通过该孔传递的任何数据是您加载的程序集(插件或扩展程序集)中声明的对象,那么您不仅可以将该对象重新加载到主应用程序域中,还可以将该程序集加载到自己的域中,这样就不可能在重新加载后与第二个应用程序域正常通信 因此,请确保不这样做,传递本机类型或在要替换的程序集之外定义的类型 我提到您可能希望加载至少两个程序集。这背后的原因是,如果要构造对象的类型,即要加载的程序集中声明的类型,没有从中派生出来,那么通过该孔传递类型的问题再次出现,并且您也会将程序集加载到主域中。处理这个问题的一个典型方法是使用某种插件管理器类,它确实来自于,并让这个管理器位于另一个域中,与其他类型的插件进行对话。这避免了通过该孔传递类型的问题
我已经在这里闲聊了一段时间,所以我就不谈了,但是有了这些信息,您应该能够更容易地理解和利用通过Google查询找到的文章。您可以创建程序集的临时副本,并使用assembly.load加载该副本。将文件监视器放置在原始文件上,并在文件监视器检测到更改时卸载/重新加载更新程序集的临时副本。这可以通过使用字节数组重载加载来完成。您需要在加载前读取程序集字节,它不会锁定文件:
byte[] readAllBytes = File.ReadAllBytes("path");
Assembly assembly = Assembly.Load(readAllBytes);
如果您从源代码动态编译DLL,您甚至不必制作副本,相反,重新编译过程应如下所示: 1) 销毁应用程序