插件类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的更多相关文章

  1. WorldWind源码剖析系列:星球类World

    星球类World代表通用的星球类,因为可能需要绘制除地球之外的其它星球,如月球.火星等.该类的类图如下. 需要说明的是,在WorldWind中星球球体的渲染和经纬网格的渲染时分别绘制的.经纬网格的渲染 ...

  2. WorldWind源码剖析系列:星球球体的加载与渲染

    WorldWind源码剖析系列:星球球体的加载与渲染 WorldWind中主函数Main()的分析 在文件WorldWind.cs中主函数Main()阐明了WorldWind的初始化运行机制(如图1所 ...

  3. WorldWind源码剖析系列:挂件类Widgets

    WorldWindow用户定制控件类中所包含的的挂件类Widgets控件主要有如下图所示的派生类.它们的类图如下所示. 鉴于挂件类Widgets及其派生类,相对简单,基本上都是些利用DirectX3D ...

  4. WorldWind源码剖析系列:插件列表视图类PluginListView和插件列表视图项类PluginListItem

    WorldWind中的插件类是个庞大的类,可以说从软件设计层面上统筹可扩展的插件体系的设计思想是WorldWind中的精华,值得学习和借鉴.插件体系中的所用到的类可以分为两大类,一类是插件类Plugi ...

  5. WorldWind源码剖析系列:设置类SettingsBase

    PluginSDK中的星球设置类WorldSettings 和WorldWind.程序设置类WorldWindSettings均继承自父类SettingsBase.类图如下所示.其中父类Setting ...

  6. WorldWind源码剖析系列:表面影像类SurfaceImage

    表面影像类SurfaceImage描述星球类(如地球)表面纹理影像.该类的类图如下. 表面影像类SurfaceImage包含的主要的字段.属性和方法如下: string m_ImageFilePath ...

  7. WorldWind源码剖析系列:星球表面渲染类WorldSurfaceRenderer

    星球表面渲染类WorldSurfaceRenderer描述如何渲染星球类(如地球)表面影像纹理.该类的类图如下. 星球类World包含的主要的字段.属性和方法如下: public const int ...

  8. WorldWind源码剖析系列:影像存储类ImageStore、Nlt影像存储类NltImageStore和WMS影像存储类WmsImageStore

    影像存储类ImageStore 影像存储类ImageStore提供了计算本地影像路径和远程影像影像URL访问的各种接口,是WmsImageStore类和NltImageStore类的基类.当划分完层次 ...

  9. WorldWind源码剖析系列:BMNG类构造函数深入分析

    BMNG构造函数深入分析 一.主要类图 二.主要功能: 1)        BMNG类 BMNG类将包含以“Blue Marble”为主题的所有可渲染影像的根节点添加到当前星球的可渲染对象列表中,包括 ...

随机推荐

  1. C#生成二维码,裁切边框

    使用google zxing生成的二维码带有白色边框,显示在报告(使用Crystal Report 水晶报表)上时,由于空间有限造成二维码过小难以扫描识别. 通过将白色边框裁切掉,可以在有限的空间内最 ...

  2. 3.Decorator Pattern(装饰者模式)

    装饰者模式: 动态地将责任附加到对象上.想要扩展功能,装饰者提供有别于继承的另一种选择. 举例: 不知道大家学校的食堂是什么点餐制度(或者大家就直接想成吃火锅,我们要火锅料 + 配菜),我们学校的点餐 ...

  3. systemd管理服务

    [root@zbs-staging-api system]# cat /lib/systemd/system/ncmulti@.service [Unit] Description=many on % ...

  4. npm WARN checkPermissions Missing write access to 解决办法

    解决办法 删除掉 C:\Users\dd\AppData\Roaming\npm-cache\ C:\Users\dd\AppData\Roaming\npm\  两个文件夹

  5. 【 js 基础 】【 源码学习 】backbone 源码阅读(三)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  6. React之设置元素的滚动条

    在React中,解耦了对DOM元素的操作,但有时我们确实需要对DOM操作,比如设置元素的滚动条,这时ref就满足了我们的需求 在低版本的react中,ref可以是一个string类型的属性,通过thi ...

  7. <Android 应用 之路> 干货集中营 ~ GankIOClient

    简介 利用干货集中营 , daimajia和他的小伙伴给我们开发者带来的福利开发的一个干货集中营客户端,主要功能在阅读干货上. Github地址: https://github.com/onlylov ...

  8. ArcGIS基于DEM计算水流方向的方法(D8算法)

    ArcGIS采用D8算法计算水流方向(9.3.1后新增),输入数据应首先完成了洼地填充处理: One of the keys to deriving hydrologic characteristic ...

  9. Android4.4中jni的native的方法无法找到的解决方案

    1.禁用代码混淆功能 LOCAL_PROGUARD_ENABLED:= disabled 2.修改混淆规则,对于类的native 方法 不要进行混淆

  10. HCTF2018 pwn题复现

    相关文件位置 https://gitee.com/hac425/blog_data/tree/master/hctf2018 the_end 程序功能为,首先 打印出 libc 的地址, 然后可以允许 ...