C#动态加载/卸载Assembly的解决方案
1. Assembly中的类要从MarshalByRefObject继承,如果你想从你自己的类来继承,那么请选用interface或者继续研究其他解决方案。
- namespace Library
- {
- public class MyClass : MarshalByRefObject
- {
- }
- }
其中MyClass的方法的返回值和参数必须是简单类型或者可序列化的。
2. 调用程序中,实现一个加载Assembly的辅助类,比如叫做LoadHelper,它也从MarshalByRefObject继承。在这个类里对Type的方法作一些封装,完成对MyClass中的方法的调用。如:
- //name:方法名
- public object InvokeMethod(string name, object obj, object[] paras)
- {
- return obj.GetType().InvokeMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, obj, paras);
- }
Type的其他方法也可以在此进行封装。总而言之,把需要进行反射的代码都写在这里。封装的形式可以有多种方式,上面这个方法是在外部创建了一个对象实例,调用时传递给这个方法,再通过反射调用其方法。其实这种方式是效率比较低的,因为那个obj要在两个AppDomain之间传递,而跨AppDomain传递对象是要将这个对象序列化和反序列化的。所以为了改善效率,可以在这里临时创建对象。
比如:
- public object InvokeInstanceMethodNotCachedAsm(string name, string assemblyFile, string typeName, object[] paras)
- {
- object obj;
- Assembly asm = Load(assemblyFile);
- obj = asm.CreateInstance(typeName);
- return obj.GetType().InvokeMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, obj, paras);
- }
甚至还可以采取将Assembly缓存的机制,这样调用起来速度更快。
3.调用程序中加载和卸载AppDomain:
- static void Load()
- {
- AppDomainSetup setup = new AppDomainSetup();
- setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
- setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
- setup.ShadowCopyFiles = "true";
- setup.ShadowCopyDirectories = "需要动态加载的Assembly所在文件夹";//影像副本目录
- setup.ApplicationName = "Dynamic";
- // Set up the Evidence
- Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
- Evidence evidence = new Evidence(baseEvidence);
- // Create the AppDomain
- appDomain = AppDomain.CreateDomain("newDomain", evidence, setup);
- loader = (LoadHelper)appDomain.CreateInstanceAndUnwrap("程序的AssemblyName", "那个辅助类的全名");
- }
- static void Unload()
- {
- AppDomain.Unload(appDomain);
- }
在这里,有三点是关键,一是创建一个新的AppDomain,二是让这个新的AppDomain允许使用影像副本文件,三是要把影像副本目录设为非主程序所在文件夹。
这是因为.Net不允许卸载一个已加载的Assembly,除非卸载整个AppDomain,允许使用影像副本,.Net就把要加载的Assembly复制到另一个文件夹(在用户配置文件夹中),但程序所在文件夹中的Assembly并不被复制。
4.创建对象实例
object obj = appDomain.CreateInstanceFromAndUnwrap("Assembly文件名含路径", "类名");
这样就创建了一个指定的类的实例,但是,不要试图对这个obj进行反射,对这个obj进行反射,不能得到其实际类型的信息,因为在主程序文件夹中没有部署那个Assembly,而只会得到其已部署的基类和接口类型,只能对这些类型进行操作。
5. 调用
如果在主程序的AppDomain中加载了所创建的对象的基类或者接口类型,那么可以调用这些类型的相关成员。
如果没有,那么就通过调用LoadHelper中的相关方法来调用。
6.卸载与替换
程序运行起来后,Assembly所在文件夹中的这个已加载的Assembly文件,是可以被删除的,因为实际上加载的那个文件是其副本,删除之后程序照样运行,而替换一个新的,也不会起作用。只有当调用上面的Unload和Load方法,卸载和重新加载后,新的Assembly才会起作用.
C#动态加载/卸载Assembly的解决方案的更多相关文章
- c#动态加载卸载DLL的方法
这篇文章介绍了c#动态加载卸载DLL的方法,有需要的朋友可以参考一下 c#中通过反射可以方便的动态加载dll程序集,但是如果你需要对dll进行更新,却发现.net类库没有提供卸载dll程序集的方法.在 ...
- 2018-2-13-C#-动态加载卸载-DLL
title author date CreateTime categories C# 动态加载卸载 DLL lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17:2 ...
- C# 动态加载卸载 DLL
我最近做的软件,需要检测dll或exe是否混淆,需要反射获得类名,这时发现,C#可以加载DLL,但不能卸载DLL.于是在网上找到一个方法,可以动态加载DLL,不使用时可以卸载. 我在写一个WPF 程序 ...
- c#动态加载卸载DLL
前段时间工作的时候遇到一个问题.就是需要每次启动程序的时候动态替换掉某个dll,所以就百度了这方面的资料.这次记录下来让自己以后可以看. 根据自己的理解,动态卸载dll需要有以下条件: 1:dll在加 ...
- js插件动态加载js、css解决方案
最近因为工作需要做了一个js自动导入的插件,一开始很天真的以为动态创建个script添加到head中就ok了,试了之后才发现了问题,就是如果同时引入了多个js文件,而且后一个文件中用到了前一个文件中的 ...
- CE驱动动态加载卸载
加载: #define DEV_KEY TEXT("Drivers\\Builtin\\WCDMA") BOOL CGPRSCTRLDlg::Load() { //DWORD dw ...
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)2----通过应用程序域AppDomain加载和卸载程序集之后,如何再返回原来的主程序域
实现目的:动态加载dll,执行完毕之后可以随时卸载掉,并可以替换这些dll,以在运行中更新dll中的类. 其实就是通过应用程序域AppDomain加载和卸载程序集. 在这方面微软有篇文章http:// ...
- 反射 type 的基本用法,动态加载插件
这里介绍反射的简单实用 MyClass类 public class MyClass { public int Age { get; set; } public string Name { get; s ...
- goloader - golang动态加载的实现
github地址:https://github.com/dearplain/goloader 这里有以前的一些思路:http://www.cnblogs.com/dearplain/p/8145985 ...
随机推荐
- 51Nod1053 最大M子段和V2 二分+DP
传送门 直接DP的话最多也只能做到\(O(nm)\),对于\(5\times 10^4\)的数据范围实在无能为力 夹克老爷提供的做法是贪心,思想大概是在调整的同时,合理构造每个选择对应的新状态,使得新 ...
- javaSE——File文件的操作
File文件操作: 在java中,File是文件和文件夹的总称. 在java中也是一个类,可以创建多个file对象. File类的一些API import java.io.File; public c ...
- 深度学习GPU集群管理软件 OpenPAI 简介
OpenPAI:大规模人工智能集群管理平台 2018年5月22日,在微软举办的“新一代人工智能开放科研教育平台暨中国高校人工智能科研教育高峰论坛”上,微软亚洲研究院宣布,携手北京大学.中国科学技术大学 ...
- android之画板功能之橡皮擦 画笔大小和画笔颜色
第一展示设置画笔颜色的功能,第二展示设置画笔大小的颜色,而第三则展示橡皮擦的功能,这节将图标颜色设置为了蓝色,并且,增加了最左边的按钮(其实,就是在gridview中多增加了一个item). 下面分别 ...
- 关于Redo Log的基本操作
1.创建新的日志组 alter database add logfile group 4 ('/u01/oracle/product/10.0.2/oradata/ORCL/redo41.log') ...
- 如何drop大表的中不用的字段 set unused column
转自 http://foxmile.blog.163.com/blog/static/81169805201143191957184/ 我 们要删除表中不用的字段,如果直接drop column,对于 ...
- Django From组件 fields widgets
一.Form组件之字段 Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容 initial=Non ...
- leetCode题解之寻找一个数在有序数组中的范围Search for a Range
1.问题描述 Given an array of integers sorted in ascending order, find the starting and ending position o ...
- Vue2学习笔记:数据交互vue-resource
基本语法 必须引入一个库:vue-resource github地址 // 基于全局Vue对象使用http Vue.http.get('/someUrl', [options]).then(succe ...
- MySql EF6 DBFirst 向导无法生成 edmx 解决方法(同:您的项目引用了最新实体框架;但是,找不到数据链接所需的与版本兼容的实体框架数据库提供程序)
使用 MySql EF6 DBfirst 生成模型时经常会遇到EF6模式无法选择的情况究其原因, 还是因为没有正确的使用 Connector/Net. 下面说一下使用方法. 使用 MySql DBFi ...