插件开发简单模型
- 格式:docx
- 大小:147.17 KB
- 文档页数:8
gom引擎插件编写例子编写 GOM 引擎插件示例引擎是游戏开发过程中的重要组成部分,它提供了游戏运行所需的各种功能。
GOM 引擎是一款功能强大且易于使用的游戏引擎,它支持插件机制,允许开发者根据自己的需求来扩展引擎功能。
本文将介绍如何编写 GOM 引擎插件,并给出一个具体的示例。
插件是用来扩展应用软件功能的一种组件。
在 GOM 引擎中,插件被用来添加新的系统、功能和工具,使用户能够以一种简单的方式自定义和扩展引擎的功能。
编写 GOM 引擎插件需要以下几个步骤:1. 创建插件项目:在开发环境中创建一个新的项目,作为插件的代码库。
2. 导入引擎库:将 GOM 引擎的库文件引入插件项目,以便在插件中使用引擎提供的功能。
3. 编写插件代码:根据插件的需求,编写相应的代码来实现功能扩展。
这部分的内容将在后文中详细介绍。
4. 构建插件:将插件代码编译成二进制文件,以便在引擎中进行加载和调用。
下面以一个简单的示例来说明如何编写 GOM 引擎插件。
假设我们要编写一个插件,用于在游戏中添加一个新角色。
这个角色需要有生命值和攻击力属性,并且能够与其他角色进行战斗。
1. 创建插件项目在开发环境中创建一个新的项目,可以使用任何你熟悉的编程语言和开发工具。
在这个示例中,我们使用 C++ 语言和Visual Studio 来创建插件项目。
2. 导入引擎库将 GOM 引擎的库文件引入插件项目,以便在插件中使用引擎提供的功能。
在示例中,我们需要引入 GOM 引擎的头文件和库文件,可以通过在项目设置中添加相关路径和文件名来实现。
3. 编写插件代码在插件项目中编写代码来实现功能扩展。
首先,我们需要定义一个新的角色类,该类包含生命值和攻击力属性,并且需要提供与其他角色战斗的功能。
```cpp// myplugin.h#include <Engine.h>class MyCharacter : public Character {private:int health;int attack;public:void SetHealth(int h) { health = h; }int GetHealth() { return health; }void SetAttack(int a) { attack = a; }int GetAttack() { return attack; }void Fight(Character* target) {this->Attack(target);target->Attack(this);}};```接下来,我们需要在插件中注册和创建该角色类的实例,并实现与引擎的接口函数。
插件产品设计方案模板一、产品概述插件是一种独立的软件模块,可为主要应用程序添加功能和特性。
本产品设计方案旨在为开发一款高质量的插件产品提供指导,确保其设计与实施能够满足用户和客户的需求。
二、需求分析在设计插件产品之前,我们需要准确了解用户和客户的需求。
通过市场调研和用户调研,我们可以收集到以下需求:1. 用户需要一款功能丰富、易于安装和使用的插件。
2. 插件需要与主应用程序无缝衔接,不影响其性能和稳定性。
3. 插件的设计应具有良好的可扩展性和定制性,以满足不同用户的个性化需求。
4. 插件的界面和交互设计应简洁直观,易于操作。
三、设计原则在设计插件产品时,我们遵循以下原则:1. 适应性原则:插件应能适应各种不同的应用场景和用户需求。
2. 简约原则:插件的设计应当简洁直观,避免过多的复杂功能和冗余操作。
3. 扩展性原则:插件应具备良好的扩展性,方便日后的功能升级和拓展。
4. 兼容性原则:插件需要与多个主要应用程序兼容,以确保用户的无缝使用体验。
四、产品架构基于需求分析和设计原则,我们提出了以下插件产品架构:1. 用户界面层:提供插件的用户界面,包括图形界面、菜单和交互控件等。
2. 功能模块层:实现插件的核心功能,包括数据处理、功能扩展等。
3. 通信接口层:与主应用程序进行接口通信,确保插件与主应用程序的无缝衔接。
4. 数据存储层:保存插件的相关设置和数据,以便于后续的使用和管理。
五、开发与测试在插件产品的开发过程中,我们需要按照以下步骤进行:1. 需求分析:准确收集用户与客户的需求,明确产品的功能和特性。
2. 原型设计:基于需求分析结果,进行界面和交互的原型设计,验证设计的可行性和用户友好性。
3. 开发与实施:根据需求和原型设计,进行插件的开发和功能实现,并与主应用程序进行集成测试。
4. 质量保证:对插件产品进行测试和质量保证,确保其稳定性和可用性。
5. 发布与升级:将插件产品发布给用户,并根据用户反馈不断升级迭代,改善产品的功能和性能。
3Dmax插件开发指南:自己设计定制化的插件在3D建模和动画设计领域中,3Dmax是最常用的软件之一。
它为用户提供了各种功能和工具,但有时我们可能需要一些额外的功能来满足特定的需求。
这时候,自己开发定制化的插件就成为一种有效的解决方案。
本文将针对初学者,提供一个详细的3Dmax插件开发指南,帮助读者自己设计和开发定制化的插件。
1. 确定需求插件的开发开始于明确需求。
首先,你需要明确自己的目标是什么,要开发的插件能为你的3Dmax工作流程带来哪些改进。
考虑到3Dmax的功能限制和你的工作需求,决定插件的主要功能是非常重要的。
2. 学习3Dmax插件开发基础知识在进行插件开发之前,你需要了解一些基础知识。
首先,你需要学习3Dmax的Scripting语言,这是用于编写插件的语言。
其次,你需要熟悉3Dmax的对象模型,包括各种对象和属性的概念与用法。
最后,你还需要了解3Dmax插件的API,这些API提供了访问和控制3Dmax功能的接口。
3. 选择合适的开发工具和编程语言3Dmax插件可以使用多种编程语言开发,比如MaxScript、Python和C++等。
根据自己的技术背景和需求,选择合适的编程语言。
同时,你还需要选择一个适合插件开发的集成开发环境(IDE),例如Autodesk的自带开发工具或者Visual Studio等。
4. 编写插件代码一旦你熟悉了3Dmax的Scripting语言和相关的API,就可以开始编写插件代码了。
首先,你需要创建一个新的脚本文件或者项目,并导入3Dmax的相关库文件。
然后,根据插件的功能需求,编写相应的代码实现。
代码编写的过程中,可以参考3Dmax的官方文档和API手册,以及一些开发者社区的资源。
5. 调试和测试插件在插件开发过程中,调试和测试是非常重要的环节。
你需要逐行检查插件代码,确保其逻辑正确无误。
另外,还需要模拟实际的工作场景,测试插件在各种情况下的稳定性和性能。
插件式开发概念
插件式开发是一种软件开发模式,它将软件系统拆分成互相独立的模块,每个模块(插件)都可以独立开发、测试、部署和升级,从而实现软件的可扩展性和可定制性。
插件式开发的核心思想是“松耦合”(loose coupling),即模块之间尽量减少相互依赖,通过明确定义接口和规范来实现模块间的通信和协作。
这样,在软件系统需要扩展或者更新时,只需要替换或添加对应的插件即可,不需要修改原有代码,从而提高了软件的可维护性和可重用性。
插件式开发可以应用于各种类型的软件系统,比如浏览器插件、文本编辑器插件、图像处理软件插件等。
开发者可以使用不同的编程语言和框架来实现插件,比如Java插件、.NET插件、Node.js插件等。
同时,插件式开发也可以与其他开发模式相结合,比如面向对象设计、微服务架构等。
在实际应用中,插件式开发可以带来很多优势,比如提高软件的可扩展性、可定制性、可维护性和可重用性,同时还能提高开发效率,使开发团队更加灵活和高效。
不过,插件式开发也需要开发者具备一定的技术水平和经验,同时需要在设计时充分考虑系统的整体结构和架构,才能实现最佳的效果。
- 1 -。
插件模型MEF: Managed Extensibility Framework(MEF)是.NET平台下的一个扩展性管理框架,它是一系列特性的集合,包括依赖注入(DI)等。
MEF为开发人员提供了一个工具,让我们可以轻松的对应用程序进行扩展并且对已有的代码产生最小的影响,开发人员在开发过程中根据功能要求定义一些扩展点,之后扩展人员就可以使用这些扩展点与应用程序交互;同时MEF让应用程序与扩展程序之间不产生直接的依赖,这样也允许在多个具有同样的扩展需求之间共享扩展程序。
MEF与MAF(Managed Addin Framework)最大不同在于:前者关注使用非常简单的方式来支持具有很强灵活性的可扩展支持,后者关注具有物理隔离、安全、多版本支持的插件平台架构。
MAF是这两个框架中较为可靠的框架。
该框架允许从应用程序中分离出插件,从而它们只依赖于您定义的接口。
如果希望处理不同的版本,MAF提供了很受欢迎的灵活性——例如,如果需要修改接口,但是为了向后兼容需要继续支持旧插件。
MAF还允许应用程序将插件加载到一个独立的应用程序域中,从而插件的崩溃是无害的,不会影响主应用程序。
所有这些特性意味着如果有一个开发团队开发一个应用程序,并且另一个(或几个)团队开发插件,MAF可以工作得很好。
MAF还特别适合于支持第三方插件。
但是为了得到MAF功能需要付出代价。
MAF是一个复杂的框架,并且即使是对于简单的应用程序,设置插件管道也很繁琐。
这正是MEF的出发点。
MEF是一个轻量级的选择,其目的是使得实现可扩展性就像是将相关的程序集复制到同一个文件夹中那样容易。
但是MEF相对于MAF有一个不同的基本原则。
MAF是一个严格的、接口驱动的模型,而MEF是一个自由使用系统,允许根据部件集合构建应用程序。
每个部件导出功能,并且所有部件都可以导入其他任何部件的功能。
该系统为开发人员提供了更大的灵活性,并且对于设计可组合的应用程序(composable applications)(由单个开发团队开发但是需要以不同方式组装的模块化程序,为单独的发布提供不同的功能实现)工作得特别好。
QT浏览器插件开发入门1 简介主流的浏览器插件开发主要分为两种:●ActiveX控件,适合IE内核的浏览器●NPAPI插件,适合Netscape浏览器的开发NPAPI全称为 Netscape Plugin Application Programming Interface在QT4.7.2下有这两种模式的开发支持,相关资料可在Qt文档网站上找到,ActiveX 开发有QT提供ActiveQT server library支持库(QT4.7.2),NPAPI开发QT4.7.2本身无此支持,需要下载相关的API,下载qt-solutions-qt-solutions-master.tar.gz,解压后qtbrowserplugin目录就是。
下面是完成的一个测试,首先做了一个功能库imagedemo,主要完成一个图片的显示功能,现在将它分别封装为ActiveX控件和NPAPI插件,供不同浏览器调用。
2 ActiveX2.1 创建QT Application工程工程名称:npgraphapp,创建时注意必须选择ActiveQT server library,如下图2.2 创建资源文件文件npgraphapp.rc中就一句话:1 TYPELIB "npgraphapp.rc"2.3 修改类npgraphapp.h在文件中增加Q_CLASSINFO信息,代码如下:#ifndef NPGRAPHAPP_H#define NPGRAPHAPP_H#include <QtGui/QtGui>class npgraphapp : public QWidget{Q_OBJECTQ_CLASSINFO("ClassID", "{4CFCDEDD-F2F6-42E9-8671-D63D7B15AA2C}");Q_CLASSINFO("InterfaceID", "{615B202B-C4F2-4C9F-B9F5-2F9D52ECF0BC}");Q_CLASSINFO("EventsID", "{C9C4EB5F-F926-4770-AA7F-50702B53DB3E}");public:npgraphapp(QWidget *parent = 0);~npgraphapp();…};#endif // NPGRAPHAPP_H2.4 修改main.cpp在文件中增加QAXFACTORY_BEGIN宏,代码如下:#include "npgraphapp.h"#include <QtGui/QApplication>#include <ActiveQt/QAxFactory>QAXFACTORY_BEGIN("{5E2C9F73-03E9-4351-9ECC-C46697D1A8D5}","{443A7F7F-FFE1-498A-AECB-D3EBCD5810CB}")QAXCLASS(npgraphapp)QAXFACTORY_END()int main(int argc, char *argv[]){QApplication a(argc, argv);if ( !QAxFactory::isServer() ){npgraphapp* w = new npgraphapp();w->show();}return a.exec();}2.5 修改工程属性增加生成事件,如下图:在命令行中编辑(注册ActiveX控件)C:\Qt\4.7.2\bin\idc.exe $(TargetPath) /idl $(IntDir)\npgraphapp.idl -version 1.0if errorlevel 1 goto VCReportErrormidl $(IntDir)\npgraphapp.idl /nologo /tlb $(IntDir)\npgraphapp.tlbif errorlevel 1 goto VCReportErrorC:\Qt\4.7.2\bin\idc.exe $(TargetPath) /tlb $(IntDir)\npgraphapp.tlbif errorlevel 1 goto VCReportErrorC:\Qt\4.7.2\bin\idc.exe $(TargetPath) /regserver2.6 注册和调用工程编译后自动生成事件会注册组件,注意看编译信息是否注册成功测试组件<OBJECT ID="npgraphdemo" CLASSID="CLSID:4CFCDEDD-F2F6-42E9-8671-D63D7B15AA2C"HEIGHT="80%" WIDTH="80%" ALIGN="LEFT" ></OBJECT>问题:如果仅仅在界面上绘制可创建QT Active库,如果界面上需调用其它QT控件或自定义的QT控件,需创建为可执行文件才可以3 NPAPI3.1 创建QT Library工程名称:npgraphdemo下载qt-solutions-qt-solutions-master.tar.gz,解压后qtbrowserplugin目录就是NPAPI 的封装支持,使用src中的文件,将下列的五个文件拷贝到工程目录下,在工程中加入qtnpapi.hqtbrowserplugin.hqtbrowserplugin_p.hqtbrowserplugin.cppqtbrowserplugin_win.cpp(windows操作系统)3.2 增加资源文件文件名称是npgraphdemo.rc,内容如下1 VERSIONINFOFILEVERSION 1,0,0,1PRODUCTVERSION 1,0,0,1FILEFLAGSMASK 0x3fL#ifdef _DEBUGFILEFLAGS 0x1L#elseFILEFLAGS 0x0L#endifFILEOS 0x4LFILETYPE 0x2LFILESUBTYPE 0x0LBEGINBLOCK "StringFileInfo"BEGINBLOCK "040904e4"BEGINVALUE "Comments", "\0"VALUE "CompanyName", "Nokia\0"VALUE "FileDescription", "grapher\0"VALUE "FileExtents", "g1n\0"VALUE "FileOpenName", "Graphable data (*.g1n)\0"VALUE "FileVersion", "1, 0, 0, 1\0"VALUE "InternalName", "npgraphdemo\0"VALUE "LegalTrademarks", "\0"VALUE "MIMEType", "application/grapher"VALUE "OriginalFilename", "npgraphdemo.dll\0"VALUE "PrivateBuild", "\0"VALUE "ProductName", "grapher npapi example\0"VALUE "ProductVersion", "1, 0, 0, 1\0"VALUE "SpecialBuild", "\0"ENDENDBLOCK "VarFileInfo"BEGINVALUE "Translation", 0x409, 1252ENDEND注意VALUE "MIMEType", "application/grapher"这句,其中的MIMEType后面字符串为自定义类型3.3 新建模块定义文件在工程选择“新建项”,创建npgraphdemo.def,如下图文件内容:LIBRARY "npgraphdemo"EXPORTSNP_GetEntryPoints @1NP_Initialize @2NP_Shutdown @33.4 修改npgraphdemo.h在文件增加Q_CLASSINFO定义,注意Q_CLASSINFO("MIME", "application/grapher:g1n:Graphable ASCII numeric data"),此处的定义要和资源文件的MIMEType定义的一致#ifndef GRAPHFROM_H#define GRAPHFROM_H#include <QtGui/QtGui>#include <qtbrowserplugin.h>QT_BEGIN_NAMESPACEclass QVBoxLayout;QT_END_NAMESPACEclass npgraphdemo : public QWidget, public QtNPBindable{Q_OBJECTQ_CLASSINFO("ClassID", "{2e5b2715-46b2-4831-ba9b-6a3b195d5ec8}")Q_CLASSINFO("InterfaceID", "{94581136-3c0c-46cc-97a1-066061356d43}")Q_CLASSINFO("EventsID", "{8c191b77-1894-45c7-9d6b-201dede95410}")Q_CLASSINFO("MIME", "application/grapher:g1n:Graphable ASCII numeric data")Q_CLASSINFO("ToSuperClass", "npgraphdemo")public:npgraphdemo(QWidget *parent = 0);~npgraphdemo();…};#endif // GRAPHFROM_H3.5 修改npgraphdemo.cpp在文件中增加QTNPFACTORY_BEGIN宏#include "npgraphdemo.h"#include "imagedemo.h"npgraphdemo::npgraphdemo(QWidget *parent) : QWidget(parent){…}npgraphdemo::~npgraphdemo(){}QTNPFACTORY_BEGIN("Qt-based Graph Plugin", "A Qt-based NSAPI plug-in that graphs numeric data"); QTNPCLASS(npgraphdemo)QTNPFACTORY_END()3.6 修改工程属性在“C/C++”下“预处理器”选项,增加”_X86_”,如下图编译即可3.7 注册和调用注册方法如下1、在命令行中输入regedit,打开注册表编辑2、在HKEYLOCALMACHIN\SOFTWARE\MozillaPlugins下新建子项@/demo3、新建字符串数据”Path”设置为动态库所在路径“D:\VictorySoft\SeisDataServer\01Develop\TestCode\npdemo\Debug\ npgraphdemo.dll”在网页中加入如下语句,可测试调用<object type="application/grapher" width=80% height="80%" >Plugin not installed!</object>问题:1、与网页的交互模式2、自动的打包和注册。
3Dmax插件开发指南:定制您自己的插件和脚本3Dmax是一款强大的三维建模、动画和渲染软件,广泛应用于电影、游戏、建筑和工业设计等领域。
为了满足用户的个性化需求,3Dmax支持插件和脚本开发,使用户能够根据自己的需求定制功能和工具。
本文将提供一个详细的指南,教你如何开发定制化的3Dmax插件和脚本。
一、了解3Dmax插件和脚本开发的基础知识1.1 插件和脚本的定义插件是一种可以扩展3Dmax功能的外部工具,可以添加新的命令、工具栏按钮或菜单项等,以实现特定的功能。
脚本是一种自动化操作的计算机程序,可以通过编写脚本语言来控制3Dmax软件的各种操作。
1.2 插件和脚本的开发环境3Dmax提供了一个强大的开发环境用于插件和脚本的编写和测试,主要包括Maxscript和.NET插件开发两种方式。
Maxscript是一种基于脚本语言的开发方式,适用于简单的功能和小型工具的开发;而.NET插件开发则提供了更多的灵活性和功能扩展的可能性。
二、使用Maxscript进行插件和脚本开发2.1 学习Maxscript语法和基本命令Maxscript是一种易学易用的脚本语言,可以轻松地执行各种3Dmax操作。
你可以通过阅读相关的文档和教程来学习Maxscript语法和常用命令,如创建对象、修改对象属性、运行动画等。
2.2 开发自定义的脚本功能首先,你需要确定你的脚本的功能和目的,然后使用Maxscript编辑器编写脚本。
例如,你可以编写一个用于自动创建树木的脚本,包括树干和树叶的生成、形状调整和材质设置等。
你可以使用Maxscript提供的一些内置函数和方法进行开发,也可以利用Maxscript的编程能力实现更复杂的功能。
2.3 创建自定义的工具栏按钮和菜单项在3Dmax的用户界面中,你可以创建自己的工具栏按钮和菜单项,以方便调用你的自定义脚本功能。
你可以通过Maxscript编辑器的界面设计工具来创建和调整工具栏按钮和菜单项的样式和位置,然后将它们与你的脚本函数关联起来。
帆软插件开发流程-概述说明以及解释1.引言1.1 概述帆软是一款功能强大的数据分析和报表开发工具,它可以帮助用户快速创建高质量的报表和数据分析应用。
而帆软插件开发则是对帆软功能的扩展和定制化开发,使用户可以根据自己的需求,自定义各种功能和特性。
插件可以包括数据源插件、发布插件、报表插件等等。
帆软插件开发流程是为了帮助开发者更好地利用帆软的强大功能进行插件开发,提高开发效率和质量。
它包括了一系列的步骤和方法,从需求分析、设计、编码、测试到发布。
具体的流程一般包括以下几个步骤:1. 需求分析:明确插件的功能和目标,了解用户需求,明确开发的方向和重点。
这一步是插件开发的基础,只有理解用户需求,才能开发出真正有价值的插件。
2. 设计:根据需求分析的结果,进行插件的整体设计和模块划分。
设计包括插件的架构设计、接口设计、数据模型设计等。
设计阶段要充分考虑插件的可扩展性和可复用性,尽量设计出灵活且易于维护的插件架构。
3. 编码:根据设计的结果,进行插件的具体编码实现。
在编码过程中要遵循规范和标准,保证代码的可读性和可维护性。
同时要注重代码的优化和性能调优,保证插件的运行效率。
4. 测试:对开发完成的插件进行全面的测试,包括单元测试、集成测试、系统测试等。
通过测试可以发现和解决插件中的问题和bug,保证插件的稳定性和可靠性。
5.发布:当插件开发完成并通过测试后,可以进行发布。
发布包括打包、文档编写、发布到平台等步骤。
发布后,用户就可以下载和使用插件了。
帆软插件开发流程的每个步骤都非常重要,缺一不可。
只有按照规范和流程进行插件开发,才能确保插件的质量和效果。
而对于开发者来说,掌握好整个流程,并结合实际情况进行灵活应用,才能更好地应对各种需求和挑战,开发出高质量的插件。
1.2 文章结构文章结构部分(1.2)的内容可以如下编写:文章结构:本文共分为引言、正文和结论三个部分进行阐述。
引言部分概述了本文的整体内容,并介绍了帆软插件开发流程的相关背景和意义。
插件开发简单模型一、前言插件模型指应用程序由一些动态的独立模块构成,每个模块均具有一个或多个服务,并满足一定的插件协议,能够借助主程序实现主程序-插件,插件-插件之间的通讯。
它定义了一套公共的接口,通过接口与插件进行通信,主要是通过反射来获取相关的属性和方法,然后再执行指定的操作。
其实,它也可以理解为定义一套通用的解决方案,通过反射来获取相应的程序集的相关类型,然后执行这些指定类型的相关操作。
它是一种即插即用的方案,更新及维护简便。
本文仅仅是描述插件开发的大体模型,设计比较简单,主要的步骤如下:(1)、定义公共的接口以及抽象类。
(2)、定义和实现相关组件。
(3)、实现通用程序集反射操作类。
其中,公共的接口和抽象类定义在组件Jasen.Framework.Core中,该组件中提供通用程序集反射操作类AssemblyUtility;具体实现的相关组件为Jasen.Framework.Oracle、Jasen.Framework.Access和Jasen.Framework.SqlServer,它们都实现了Jasen.Framework.Core中的公共接口。
客户端可以根据实际情况来进行相应的操作。
相关组件图如下:二、公共接口和抽象类的定义以及相关组件的定义和实现首先,定义公共的接口以及抽象类,如下类图所示,定义一个公共的接口IDataTable,定义一个抽象类DataTable,这些公共的类型放置在最顶端的程序集中。
而其他组件将分别重新创建,实现相对应的功能,如SqlServerDataTable、OracleDataTable和AccessDataTable实现各自的功能。
注意:Assembly.LoadFile(file)动态加载程序集时,该程序集在当前的运行环境中必须不存在的,否则可能会出现意想不到的数据异常,因此相关组件的实现必须是独立的(仅仅是实现公共的接口)。
三、通用程序集反射操作类的实现下面的AssemblyUtility主要是对程序集操作的通用类,可以根据指定目录以及文件列表动态获取相应的程序集。
同时,也可以通过目录,文件以及程序集获取相关的类型集合和对象集合。
其中需要注意的是,实现的子类必须提供默认构造函数。
客户端可以通过该类获取相应的类型和对象集合,然后再执行相应的操作。
这些操作都是通过动态加载程序集来实现的,代码如下所示:public static class AssemblyUtility{public static IEnumerable<Type> GetImplementdTypesByDirectory<T>(string baseDi rectory){IList<Assembly> assemblies= GetAssemblies(baseDirectory);List<Type> types = new List<Type>();foreach (Assembly assembly in assemblies){types.AddRange(GetImplementdTypes<T>(assembly));}return types;}public static IEnumerable<Type> GetImplementdTypes<T>(string assemblyFile){if (!File.Exists(assemblyFile)){return null;}{return GetImplementdTypes<T>(Assembly.LoadFile(assemblyFile));}catch (Exception ex){return null;}}public static IEnumerable<Type> GetImplementdTypes<T>(Assembly assembly){if (assembly == null){return null;}return assembly.GetExportedTypes().Where(p =>p.IsSubclassOf(typeof(T)) && (!p.IsAbstract) && (!p.IsInterface));}public static IList<T> GetImplementedObjectsByDirectory<T>(string baseDirectory) {IList<Assembly> assemblies = GetAssemblies(baseDirectory);List<T> entities = new List<T>();foreach (Assembly assembly in assemblies){entities.AddRange(GetImplementedObjects<T>(assembly));}return entities;}public static IList<T> GetImplementedObjects<T>(string assemblyFile){if (!File.Exists(assemblyFile)){return null;}try{return GetImplementedObjects<T>(Assembly.LoadFile(assemblyFile));}catch (Exception ex)return null;}}public static IList<T> GetImplementedObjects<T>(Assembly assembly) {if (assembly == null){return null;}IEnumerable<Type> types = GetImplementdTypes<T>(assembly); var result = new List<T>();foreach (Type type in types){ConstructorInfo constructor = type.GetConstructor(new Type[0]);if (constructor == null){continue;}object instance = Activator.CreateInstance(type);if (instance is T){result.Add((T)instance);}}return result;}public static IList<Assembly> GetAssemblies(string baseDirectory){if (!Directory.Exists(baseDirectory)){return new List<Assembly>();}string[] files = Directory.GetFiles(baseDirectory, "*.dll");return GetAssemblies(files);}public static IList<Assembly> GetAssemblies(string[] assemblyFiles){IList<Assembly> assemblies = new List<Assembly>();try{foreach (string file in assemblyFiles){if (!File.Exists(file)||(!file.EndsWith(".dll",StringComparison.InvariantCultureI gnoreCase))){continue;}assemblies.Add(Assembly.LoadFile(file));}}catch (Exception ex){return new List<Assembly>();}return assemblies;}}public static IEnumerable<Type> GetImplementdTypesByDirectory<T>(string ba seDirectory)public static IEnumerable<Type> GetImplementdTypes<T>(string assemblyFile) public static IList<T> GetImplementedObjects<T>(Assembly assembly)以上3个方法根据不同的参数(目录、地址、程序集)来动态获取程序集中的特定类型集合,这些类型为类型T的类或者子类(非抽象类和接口)。
public static IList<T> GetImplementedObjectsByDirectory<T>(string baseDirecto ry)public static IList<T> GetImplementedObjects<T>(string assemblyFile)public static IList<T> GetImplementedObjects<T>(Assembly assembly)而以上3个方法根据不同的参数(目录、地址、程序集)来动态获取程序集中的特定对象集合,这些对象为类型T的类或者子类(非抽象类和接口)的实例。
当组件中子类存在有参构造函数时,必须实现默认构造函数。
从如下代码可以看出:如果默认构造函数不存在,将不会添加该对象实例。
ConstructorInfo constructor = type.GetConstructor(new Type[0]);if (constructor == null){continue;}object instance = Activator.CreateInstance(type);if (instance is T){result.Add((T)instance);}四、通用程序集反射操作类的单元测试AssemblyUtility类主要的单元测试如下,仅验证了正确的情况,代码如下:public class AssemblyUtilityTest{[TestMethod()]public void GetAssembliesTest(){string assemblyPath = AppDomain.CurrentDomain.BaseDirectory+"\\Files\\";IList<Assembly> result = AssemblyUtility.GetAssemblies(assemblyPath);Assert.IsNotNull(result);Assert.AreEqual(3, result.Count);}[TestMethod()]public void GetAssembliesByFilesTest(){string[] assemblyFiles = new string[] { AppDomain.CurrentDomain.BaseDirectory + "\\Jasen.Framework.Core.dll",AppDomain.CurrentDomain.BaseDirectory + "\\Jasen.Framework.Core.Test. dll","www","ww.dll"};IList<Assembly> result = AssemblyUtility.GetAssemblies(assemblyFiles);Assert.IsNotNull(result);Assert.AreEqual(2, result.Count);}[TestMethod()]public void GetImplementedObjectsByDirectoryTest(){string assemblyDir = AppDomain.CurrentDomain.BaseDirectory + "\\Files\\";IList<DataTable> result = AssemblyUtility.GetImplementedObjectsByDirectory<D ataTable>(assemblyDir);Assert.IsNotNull(result);Assert.AreEqual(3, result.Count);}[TestMethod()]public void GetImplementedObjectsTest(){string assemblyFile =AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Jasen.F ramework.Oracle.dll";IList<DataTable> result = AssemblyUtility.GetImplementedObjects<DataTable>(a ssemblyFile);Assert.IsNotNull(result);Assert.AreEqual(1, result.Count);}[TestMethod()]public void GetImplementedTypesTest(){string assemblyFile = AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Jasen. Framework.Oracle.dll";IEnumerable<Type> types = AssemblyUtility.GetImplementdTypes<DataTable>(a ssemblyFile);Assert.IsNotNull(types);int count = 0;foreach (var type in types){Assert.IsTrue(type.IsSubclassOf(typeof(DataTable)));Assert.IsFalse(type.IsAbstract);Assert.IsFalse(type.IsInterface);count++;}Assert.AreEqual(1, count);}[TestMethod()]public void GetImplementdTypesByDirectoryTest(){string assemblyDir = AppDomain.CurrentDomain.BaseDirectory + "\\Files\\";IEnumerable<Type> types = AssemblyUtility.GetImplementdTypesByDirectory<D ataTable>(assemblyDir);Assert.IsNotNull(types);int count = 0;foreach (var type in types){Assert.IsTrue(type.IsSubclassOf(typeof(DataTable)));Assert.IsFalse(type.IsAbstract);Assert.IsFalse(type.IsInterface);count++;}Assert.AreEqual(3, count);}}五、总结全文中主要围绕AssemblyUtility通用类来进行讲解的,仅仅是插件开发的一个思路。