WorldWind源码剖析系列:插件类Plugin、插件信息类PluginInfo和插件编译器类PluginCompiler
插件类Plugin是所有由插件编译器加载的插件子类的抽象父类,提供对插件的轻量级的访问控制功能。
插件信息类PluginInfo用来存储关于某个插件的信息的类,可以理解为对插件类Plugin类的进一步抽象封装,提供了比插件类Plugin更为详细的插件信息。
插件编译器类PluginCompiler用来加载插件脚本,编译和执行插件。
在加载的时候,WorldWind主程序首先调用PluginCompiler函数,在WorldWind根目录的Plugins目录中进行查找,将所有存在的插件文件添加到插件列表中,最后根据用户选择加载运行。这个插件文件的类型既可以是像.cs这类的未编译的源代码,又可以是像.dll这类已经编译为二进制文件的可直接运行的库文件。
在代码中,查找过程如下:
MainApplication.OpenStartupWorld()
一>OpenWorld();
一>InitializePluginCompiler();
compiler=new PluginCompiler(this,pluginRoot);
compiler.FindPlugins(Assembly.GetExecutingAssembly());
//查找程序集内部的的插件类
compiler.FindPlugins();
//查找外部插件类,在plugin文件夹中
compiler.LoadStartupPlugins();
//加载插件
以下代码省略……
插件相关类的关系如下图所示:

图1 WorldWind的插件运行机制
这三个类的类图如下。


插件类Plugin包含的主要的字段、属性和方法如下:
protected MainApplication m_Application:加载该插件的主程序。
protected string m_PluginDirectory:插件所在的目录。
protected bool m_isLoaded:插件是否被加载的标识。
public virtual void Load():加载插件的虚函数,可被子类重载。被虚函数public virtual void PluginLoad( MainApplication parent, string pluginDirectory )调用。
public virtual void UnLoad():卸载插件的虚函数,可被子类重载。被虚函数public virtual void PluginUnload()调用。
插件信息类PluginInfo包含的主要的字段、属性和方法如下:
Plugin m_plugin:所封装的插件对象。
string m_fullPath:插件的完全路径。
string m_name:从插件注释头节点中获取的插件的名称。
string m_description:插件的描述。
string m_developer:插件的开发者。
string m_webSite:插件的网络站点。
string m_references:插件的引用。
public string ID:只读属性实际返回的的是不含扩展名的插件名称。
public bool IsCurrentlyLoaded:检查一个插件是否为当前正在加载的插件。
public bool IsLoadedAtStartup:设置插件是否在主程序已启动时就加载的标识。
private void ReadMetaData():该方法从源文件的头节点中读取元数据字符串。
static void FindTagInLine(string inputLine, string tag, ref string value) :该静态方法从输入的一行源数据中返回指定的tag节点的值。
插件编译器类PluginCompiler包含的主要的字段、属性和方法如下:
MainApplication worldWind:加载该插件的主程序。
const string LogCategory = "PLUG":加载该插件时的日志分类类别。
Hashtable codeDomProviders = new Hashtable():codeDomProviders是用来存储codeDomProvider对象的哈希表对象。其中,CodeDom在Microsoft .NET Framework 的中文全名是“代码文档对象模型”, 使用该模型建立的代码文档可以被.NET Framework编译成应用程序集。CodeDomProvider 为抽象类,可用于创建和检索代码生成器和代码编译器的实例。 代码生成器可用于以特定的语言生成代码,而代码编译器可用于将代码编译为程序集,其派生类有CsharpCodeProvider、VBCodeProvider和JScriptCodeProvider。
CompilerParameters cp = new CompilerParameters():表示用于调用编译器的参数。提供用C#动态编译、执行代码的能力。
ArrayList m_plugins = new ArrayList():存储插件的列表。
StringCollection m_worldWindReferencesList = new StringCollection():主程序对插件的引用列表。StringCollection类型表示字符串的集合。
string m_pluginRootDirectory:插件的根路径。
public PluginCompiler( MainApplication worldWind, string pluginDirectory ):方法实例化一个插件编译器对象。
public void AddCodeProvider( CodeDomProvider cdp ): 方法CodeDomProvider的派生类子对象到哈希表对象codeDomProviders中。因为用户可能是用C#、VB或Jscript等语言开发插件。
public void FindPlugins( Assembly assembly ):从指定的程序集中查找插件实例,并将找到的插件信息类PluginInfo对象保存到列表m_plugins中。查找条件是:找到的类型必须是类类型、公开的、父类是Plugin类。
public void FindPlugins():构造或更新可用的插件列表。内部调用void AddPlugin(string path)方法。
void AddPlugin(string path) :从指定的路径中生成插件信息类PluginInfo对象并将其保存到列表m_plugins中。内部调用public bool HasCompiler(string fileExtension)和static public bool IsPreCompiled(string fileExtension)。
public void LoadStartupPlugins():加载那些被设置为在主程序一启动时就加载的插件。内部调用public void Load(PluginInfo pi) 方法。
public void Load(PluginInfo pi):加载指定的插件。具体实现为:程序集反射出插件对象或动态编译生成插件所在的程序集对象,然后再通过从程序集中返回需要加载的插件对象,得到插件对象后再通过调用的是Plugin类的派生类重载后的PluginLoad函数实现插件的真正加载功能。内部主要调用Assembly.LoadFile(pi.FullPath)、Assembly Compile( PluginInfo pi, CodeDomProvider cdp)和static Plugin GetPluginInterface(Assembly asm) 等方法。
public void Unload(PluginInfo pi) :卸载指定的插件,卸载时实际上调用的是Plugin 类或Plugin 派生类重载后的PluginUnload函数。
public void Uninstall(PluginInfo pi):卸载程序集并删除其文件。内部调用Unload。
public void Dispose():关闭并析构插件列表中的所有插件对象。
Assembly Compile( PluginInfo pi, CodeDomProvider cdp ):使用指定的编译器动态编译一个文件生成程序集对象,内部包含插件对象。
static Plugin GetPluginInterface(Assembly asm) :从指定的程序集中返回需要加载的插件对象。查找条件是:找到的类型必须是类类型、公开的、父类是Plugin类。
附:
AppDomain 类:表示应用程序域,它是一个应用程序在其中执行的独立环境。 此类不能被继承。
应用程序域(由 AppDomain 对象表示)为执行托管代码提供隔离、卸载和安全边界。
- 使用应用程序域隔离可能终止进程的任务。 如果正在执行任务的 AppDomain 的状态变得不稳定,则可以卸载 AppDomain,但不会影响进程。当进程必须不重新启动而长时间运行时,这一点很重要。 还可使用应用程序域隔离不应共享数据的任务。
- 如果程序集被加载到默认应用程序域中,则当进程运行时将无法从内存中卸载该程序集。 但是,如果打开另一个应用程序域来加载和执行程序集,则卸载该应用程序域时也会同时卸载程序集。 使用此技术最小化长时间运行的进程的工作集,这些进程偶尔会使用大型 DLL。
多个应用程序域可以在一个进程中运行;但是,在应用程序域和线程之间没有一对一的关联。 多个线程可以属于一个应用程序域,尽管给定的线程并不局限于一个应用程序域,但在任何给定时间,线程都在一个应用程序域中执行。
使用 CreateDomain 方法创建应用程序域。AppDomain 实例用于加载和执行程序集(Assembly)。当不再使用 AppDomain 时,可以将它卸载。
AppDomain 类实现一组事件,这些事件使应用程序可以在加载程序集、要卸载应用程序域或引发未经处理的异常时进行响应。
WorldWind源码剖析系列:插件类Plugin、插件信息类PluginInfo和插件编译器类PluginCompiler的更多相关文章
- WorldWind源码剖析系列:星球类World
星球类World代表通用的星球类,因为可能需要绘制除地球之外的其它星球,如月球.火星等.该类的类图如下. 需要说明的是,在WorldWind中星球球体的渲染和经纬网格的渲染时分别绘制的.经纬网格的渲染 ...
- WorldWind源码剖析系列:星球球体的加载与渲染
WorldWind源码剖析系列:星球球体的加载与渲染 WorldWind中主函数Main()的分析 在文件WorldWind.cs中主函数Main()阐明了WorldWind的初始化运行机制(如图1所 ...
- WorldWind源码剖析系列:挂件类Widgets
WorldWindow用户定制控件类中所包含的的挂件类Widgets控件主要有如下图所示的派生类.它们的类图如下所示. 鉴于挂件类Widgets及其派生类,相对简单,基本上都是些利用DirectX3D ...
- WorldWind源码剖析系列:插件列表视图类PluginListView和插件列表视图项类PluginListItem
WorldWind中的插件类是个庞大的类,可以说从软件设计层面上统筹可扩展的插件体系的设计思想是WorldWind中的精华,值得学习和借鉴.插件体系中的所用到的类可以分为两大类,一类是插件类Plugi ...
- WorldWind源码剖析系列:设置类SettingsBase
PluginSDK中的星球设置类WorldSettings 和WorldWind.程序设置类WorldWindSettings均继承自父类SettingsBase.类图如下所示.其中父类Setting ...
- WorldWind源码剖析系列:表面影像类SurfaceImage
表面影像类SurfaceImage描述星球类(如地球)表面纹理影像.该类的类图如下. 表面影像类SurfaceImage包含的主要的字段.属性和方法如下: string m_ImageFilePath ...
- WorldWind源码剖析系列:星球表面渲染类WorldSurfaceRenderer
星球表面渲染类WorldSurfaceRenderer描述如何渲染星球类(如地球)表面影像纹理.该类的类图如下. 星球类World包含的主要的字段.属性和方法如下: public const int ...
- WorldWind源码剖析系列:影像存储类ImageStore、Nlt影像存储类NltImageStore和WMS影像存储类WmsImageStore
影像存储类ImageStore 影像存储类ImageStore提供了计算本地影像路径和远程影像影像URL访问的各种接口,是WmsImageStore类和NltImageStore类的基类.当划分完层次 ...
- WorldWind源码剖析系列:BMNG类构造函数深入分析
BMNG构造函数深入分析 一.主要类图 二.主要功能: 1) BMNG类 BMNG类将包含以“Blue Marble”为主题的所有可渲染影像的根节点添加到当前星球的可渲染对象列表中,包括 ...
随机推荐
- linux系统编程:cp的另外一种实现方式
之前,这篇文章:linux系统编程:自己动手写一个cp命令 已经实现过一个版本. 这里再来一个版本,涉及知识点: linux系统编程:open常用参数详解 Linux系统编程:简单文件IO操作 /*= ...
- HDU1029(KB12-B)
Ignatius and the Princess IV Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32767 K ( ...
- Angular环境搭建
Angular4 随笔(一)----环境搭建 1.下载node.js 第一步:在浏览器中搜索node.js官网(https://nodejs.org/zh-cn/),根据自己系统下载相应版本,下载完成 ...
- 【代码笔记】iOS-动画的跳转
一,工程图. 二,代码. //点击任何处跳转到页面 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CATransi ...
- Mac 上用 Homebrew 安装 .NET Core 1.0 RC4 004771
年级大了,其实并不是很喜欢升级到最新版,特别是不怎么爱用还没有 Release 的版本了.虽然 .NET Core 已经是 RC4,但毕竟还没有 Release.可过年回来,用 yeoman 创建了一 ...
- css 单行/多行文字垂直居中问题
例子可以直接看这里http://www.zhangxinxu.com/study/200911/line-height-text-v-center.html 这篇文章中有一点点解释http://blo ...
- ajax请求json数据跨域问题(转)
一.后台代理技术 由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制. 具体操作如下: 1.在localhost:81/a.html中,向同源下的某个代理程序发出请求 $ ...
- Finereport和Finebi的区别
1.问题描述 大家现在可能都知道,目前帆软旗下特色产品主要是FineReport和FineBI,但是部分用户可能会有个疑问:FineReport和FineBI到底有什么区别? 2.产品介绍FineRe ...
- terminate called after throwing an instance of 'std::bad_alloc'
这个错误,网上搜索到的资料大多是指向内存不足或者内存碎片问题,如下链接 http://bbs.csdn.net/topics/330000462 http://stackoverflow.com/qu ...
- 【mongoDB运维篇③】replication set复制集
介绍 replicattion set 多台服务器维护相同的数据副本,提高服务器的可用性,总结下来有以下好处: 数据备份与恢复 读写分离 MongoDB 复制集的结构以及基本概念 正如上图所示,Mon ...