Joa*_*nge 5 .net c# reflection assemblies
是否可以通过将程序集流式传输到内存中来实现此目的?如果是这样,那怎么做呢?
原因:
我不想锁定加载的DLL.我希望能够动态加载,更改代码,再次编译和重新加载它
ang*_*son 19
据我了解,您想要执行以下操作:
基本上,您所描述的是各种插件系统,您可以使用阴影dll和应用程序域来实现.
首先,为了卸载程序集,不需要退出应用程序,您需要将该程序集加载到单独的应用程序域中.你应该能够在网上找到关于如何做到这一点的好教程.
这是一个谷歌查询,应该为您提供一些起始文章.
其次,为了避免将程序集锁定在磁盘上,这很简单,只需先复制它,然后加载副本而不是原始副本.当然,你将锁定副本,但副本只是你的应用程序的临时文件,所以没有人应该有兴趣修改该文件.这使原始文件解锁并可修改.
Assembly.Load
如果您有多个将要加载和替换的程序集,您应该尝试使用阴影而不是使用可以从字节数组加载程序集的重载.
例如,如果您的插件程序集A.dll依赖于第二个程序集B.dll,并且在调用Assembly.Load之前使用字节数组技巧将A.dll加载到内存中,则需要在应用程序中处理程序集解析调用domain(你可以在需要加载程序集时告诉你,并且"帮助"加载过程),或者你需要确保B.dll首先以加载A.dll的方式加载,否则从中加载A.dll内存将自动从磁盘加载B.dll.
以下是有关使用单独的应用程序域的更多信息.
当您创建另一个应用程序域时,通过在.NET中使用AppDomain类,您将在内存中创建一个单独的隔离专区,您可以在其中运行代码.它实际上与您的主应用程序域分开,并且只有一个穿过隔离墙的小孔.
通过这个洞,您可以传递消息,如方法调用和数据.
构建新的应用程序域后,在其中加载一个或多个程序集.通常,如果要为此类加载构建要加载到其中的程序集,则将加载1;如果尚未加载,则加载2(下面将详细介绍).
加载程序集后,在另一个应用程序域中构造一个或多个对象,使第一个应用程序域可以与这些对象进行通信.这些对象需要从MarshalByRefObject继承,MarshalByRefObject是一个允许发生魔法的类.
基本上会发生这种情况.在其他应用程序域内,创建了加载到该应用程序域中的类型的对象.此类型来自MarshalByRefObject.构造此对象的请求来自第一个应用程序域,并且在此应用程序域内部构造了一个代理对象,该对象看起来像是在同一个应用程序域中创建的相同对象.代理通过那个洞与另一个对象交谈.
所以现在你有两个应用程序域,两个对象,每边一个,并且对象相互通信.
通过此设置,稍后您可以切断对象之间的连接,然后卸载其他应用程序域,这基本上会拆除该隔离专区.然后,如果您愿意,可以构建一个新的第二个应用程序域,并重新开始,实际上再次从磁盘重新加载程序集.
需要注意的一件事是你通过这个洞的数据.如果您通过该孔传递的任何数据是在您加载的程序集(您的插件或扩展程序集)中声明的对象,那么您不仅会将该对象返回到您的主应用程序域,您的主应用程序域也将将该程序集加载到其自己的域中,从而使重新加载后无法正确地与第二个应用程序域通信.
因此,请确保不要这样做,传递本机类型或在要替换的程序集之外定义的类型.
我提到你可能想要加载至少两个程序集.这背后的原因是,如果你想构造一个对象的类型,你要加载的那个程序集中声明的类型,不会从MarshalByRefObject下降,那么再次通过那个洞传递类型的问题就会出现,并且您也可以将程序集加载到主域中.处理此问题的一种典型方法是使用某种插件管理器类,它确实来自MarshalByRefObject,并让此管理器位于其他域中并与其他类型进行通信.这避免了通过该洞传递类型的问题.
我已经在这里漫游了一段时间,所以我会留下它,但是通过这些信息,您应该能够理解并利用通过Google查询找到的文章更容易一些.
Eli*_*sha 11
它可以通过使用字节数组的Load重载来完成.您需要在加载之前读取汇编字节,它不会锁定文件:
byte[] readAllBytes = File.ReadAllBytes("path");
Assembly assembly = Assembly.Load(readAllBytes);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6835 次 |
最近记录: |