AppDomain实现【插件式】开发

 近期项目中需要实现“热插拔”式的插件程序,例如:定义一个插件接口;由不同开发人员实现具体的插件功能类库;并最终在应用中调用具体插件功能。

 此时需要考虑:插件执行的安全性(隔离运行)和插件可卸载升级。说到隔离运行和可卸载首先想到的是AppDomain。

 那么AppDomain是什么呢?

一、AppDomain介绍

 AppDomain是.Net平台里一个很重要的特性,在.Net以前,每个程序是"封装"在不同的进程中的,这样导致的结果就造就占用资源大,可复用性低等缺点.而AppDomain在同一个进程内划分出多个"域",一个进程可以运行多个应用,提高了资源的复用性,数据通信等. 详见

 CLR在启动的时候会创建系统域(System Domain),共享域(Shared Domain)和默认域(Default Domain),系统域与共享域对于用户是不可见的,默认域也可以说是当前域,它承载了当前应用程序的各类信息(堆栈),所以,我们的一切操作都是在这个默认域上进行."插件式"开发很大程度上就是依靠AppDomain来进行.

 应用程序域具有以下特点:

必须先将程序集加载到应用程序域中,然后才能执行该程序集。

一个应用程序域中的错误不会影响在另一个应用程序域中运行的其他代码。

能够在不停止整个进程的情况下停止单个应用程序并卸载代码。不能卸载单独的程序集或类型,只能卸载整个应用程序域。

二、基于AppDomain实现“热拔式插件”

 通过AppDomain来实现程序集的卸载,这个思路是非常清晰的。由于在程序设计中,非特殊的需要,我们都是运行在同一个应用程序域中。

 由于程序集的卸载存在上述的缺陷,我们必须要关闭应用程序域,方可卸载已经装载的程序集。然而主程序域是不能关闭的,因此唯一的办法就是在主程序域中建立一个子程序域,通过它来专门实现程序集的装载。一旦要卸载这些程序集,就只需要卸载该子程序域就可以了,它并不影响主程序域的执行。 

 实现方式如下图:

  

AppDomain实现【插件式】开发

1、AssemblyDynamicLoader类提供创建子程序域和卸载程序域的方法;
2、RemoteLoader类提供装载程序集、执行接口方法;
3、AssemblyDynamicLoader类获得RemoteLoader类的代理对象,并调用RemoteLoader类的方法;
4、RemoteLoader类的方法在子程序域中完成;

 那么AssemblyDynamicLoader 和 RemoteLoader 如何实现呢?

 1、首先定义RemoteLoader用于加载插件程序集,并提供插件接口执行方法  

public class RemoteLoader : MarshalByRefObject { private Assembly _assembly; public void LoadAssembly(string assemblyFile) { _assembly = Assembly.LoadFrom(assemblyFile); } public T GetInstance<T>(string typeName) where T : class { if (_assembly == null) return null; var type = _assembly.GetType(typeName); if (type == null) return null; return Activator.CreateInstance(type) as T; } public object ExecuteMothod(string typeName, string args) { if (_assembly == null) return null; var type = _assembly.GetType(typeName); var obj = Activator.CreateInstance(type); if (obj is IPlugin) { return (obj as IPlugin).Exec(args); } return null; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxwjz.html