Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不使用assembly.load的情况下加载程序集?_C#_.net_Reflection_Assemblies - Fatal编程技术网

C# 如何在不使用assembly.load的情况下加载程序集?

C# 如何在不使用assembly.load的情况下加载程序集?,c#,.net,reflection,assemblies,C#,.net,Reflection,Assemblies,是否可以通过将程序集流式传输到内存中来实现这一点?如果是这样的话,如何做到这一点 原因: 我不想锁定加载的dll。我希望能够动态加载、更改代码、编译并再次重新加载它据我所知,您需要执行以下操作: 将程序集从磁盘加载到内存中,以便使用其中的数据或调用其中的代码 以后可以卸载程序集 避免在磁盘上锁定程序集,这样您就可以在不退出应用程序(或先卸载程序集)的情况下对其进行修改 基本上,您所描述的是一个插件系统,您可以通过使用阴影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) 销毁应用程序