插件契约介绍

我们知道,要基于平台(容器)加插件的这种模式进行开发,我们必须定义一组契约,用于约束模块插件开发,也就是说,模块插件需要遵守一定的标准进行开发,才能正常被容器调用,这就是IModule所定义的内容。

IModule/// <summary>
/// 插件接口定义。
/// </summary>
public interface IModule:IPrivilegObject
{/// <summary>/// 获取模块的名称。/// </summary>/// <remarks>该值由开发者自己生成。</remarks>new string Name { get;}/// <summary>/// 获取模块的版本信息。/// </summary>/// <remarks>该值为对象的版本信息,从程序集中读取,也可由开发者自己生成。</remarks>string Version { get;}/// <summary>/// 获取模块的开发者信息。/// </summary>/// <remarks>该值为对象的开发组织或个人说明信息,从程序集中读取。</remarks>string Developer { get;}/// <summary>/// 获取模块的分组信息。/// </summary>/// <remarks>该值为模块的分组,由开发人员定义,也可以在安装后定义。</remarks>string Group { get; }/// <summary>/// 获取模块的介绍。/// </summary>/// <remarks>模块的介绍与说明信息,由开发人员定义,也可以在安装后定义。</remarks>string Description { get;}/// <summary>/// 获取对象的图标。/// </summary>/// <remarks>对象的图标主要用于加载模块时用。</remarks>Image Icon { get;}/// <summary>/// 当功能模块成功启动后触发。/// </summary>event System.EventHandler Started;/// <summary>/// 在关闭模块之前触发该事件。/// </summary>event System.EventHandler Exited;/// <summary>/// 关闭当前模块。/// </summary>void Close();/// <summary>/// 运行当前模块。/// </summary>/// <param name="parameters">模块运行的初始参数列表。</param>void Start(params object[] parameters);
}

IModule定义了模块名称及模块被调用的方法Run(),以及被平台加载和关闭的事件,从定义可我们看到IModule继续自IPrivilegObject。

IPrivilegObject/// <summary>
/// 系统权限对象的基本规范。
/// </summary>
public interface IPrivilegObject
{/// <summary>/// 获取权限对象的全局唯一标识符(GUID)。/// </summary>/// <remarks>该值由实现类得到,默认值实现类的GUID值。</remarks>System.Guid Guid { get; }/// <summary>/// 获取对象权限对象所有者名称。/// </summary>/// <remarks>该值用于说明权限所有者的名称。</remarks>string Name { get;}
}

IPrivilegObject为权限对象接品,平台(运行容器)可以使用其鉴权系统对其实现权限检查,关于系统的权限设计我会在后面专门进行说明。

在模块插件的接口中,我们看到了很多关于模块自描述的信息,比如名称、说明、类型、程序集、版本号以及开发者等等,定义这些信息的目的在于对模块的自描述,资源管理平台在安装模块的过程中读取这些元数据并存储在数据库,以方便对系统中插件的管理。

模块元数据中定义的程序集、类型信息用于容器反射调用插件,这也是平台+插件所依赖的关键技术。

直接实现IMobile接口

开发人员可以选择直接实现IModule接口极其相关成员以实现一个业务插件,下面来一个简单的实现:

Calculatorclass Calculator:IModule
{#region IModule 成员public void Close(){}public string Developer{get{return "james/agilelab.cn";}}public event EventHandler Exited;public string Group{get{throw new Exception("The method or operation is not implemented.");}}public System.Drawing.Image Icon{get{return null;}}public string ModuleName{get{return this.Name;}}public void Run(params object[] parameters){try{System.Diagnostics.Process.Start("calc.exe");}catch{}}public event EventHandler Started;public string Version{get{return System.Reflection.Assembly.GetAssembly(this.GetType()).GetName().Version.ToString(); }}#endregion#region IObject 成员public string Assembly{get{return System.Reflection.Assembly.GetAssembly(this.GetType()).GetName().Name;}}public string Description{get{return "外部工具,计算器";}}public string Type{get{return this.GetType().ToString();}}#endregion#region IPrivilegObject 成员public Guid Guid{get{return new Guid("4B538C7C-99BD-46aa-9244-C594239D354A");}}public string Name{get{return "计算器";}}#endregion#region IAddIn 成员public void Start(params object[] parameters){this.Run(parameters);}#endregion
}

原则说上,这种方法是可以的,但是在具体开发过程中,非必要情况下,不必要直接实现IModule接口,AgileEAS.NET平台提供了一组默认的基础实现。

复用AgileEAS.NET平台基础实现

开发人员直接实现IModule接口的问题在于会写大量与业务无关的代码,鉴于此问题,AgileEAS.NET平台针对WebForm和WinForm应用提供了一系统的基础实现,开发人员选择在合适的基类上继承并重写与业务相关的信息,下面是一个简单例子:

UserControl2public partial class UserControl2 : EAS.Windows.UI.Controls.ExplorerControl
{public UserControl2(){InitializeComponent();}public override Guid Guid{get{return new Guid("2B6F6C7F-2382-433f-87D7-D601CE378081");}}public override string ModuleName{get{return "模块插件例子";}}public override string Description{get{return "例子,还是例子";}}public override void Run(params object[] parameters){this.Message = "正在初始化插件...";}private void button1_Click(object sender, EventArgs e){MessageBox.Show("来来来,大家一起玩");}
}

可以看到,代码相比直接实现IModule接口要简介的多,AgileEAS.NET提供了如下的默认实现:

EAS.Windows.UI.Forms.ModuleForm

WinForm模块插件的基类实现(独立的运行窗体),开发人员重写ModuleName、Description、Guid属性及入口方法Run即可。

EAS.Windows.UI.Controls.ModuleControl

WinForm模块插件的基类实现(内嵌入运行容器的业务控件),开发人员重写ModuleName、Description、Guid属性及入口方Run法即可。

EAS.Windows.UI.Controls.ExplorerControl

WinForm模块插件的基类实现(内嵌入运行容器的业务控件),相比较EAS.Windows.UI.Controls.ModuleControl提供了Close方法等、消息通知等增强功能,在开发过程中一般直接取代EAS.Windows.UI.Controls.ModuleControl。

EAS.Web.UI.ModulePage

WebForm模块插件的基类实现(独立的运行面),开发人员重写ModuleName、Description、Guid属性即可,WebForm插件因为其特殊性无需处理入口方法。

EAS.Windows.UI.Controls.ModuleControl

WebForm模块插件的基类实现(内嵌入运行容器的业务控件),开发人员重写ModuleName、Description、Guid属性即可。

别外,针对项目中大量的数据绑带应用业务,AgileEAS.NET平台配合数据绑定接口IDataBind也提供了如下基础实现:

EAS.Windows.UI.Data.Form、EAS.Windows.UI.Data.ModuleForm、EAS.Windows.UI.Data.Control、EAS.Windows.UI.Data.ExplorerControl。

EAS.Web.UI.Data.Page、EAS.Windows.Web.Data.ModulePage、EAS.Web.UI.Data.Control、EAS.Windows.Web.Data.ModuleControl。

AgileEAS.NET除了提供这一系列的基础实现之外,还提供了基于WinForm和WebForm开发常用的一组基础实现指导组件,称为GUI模板(EAS.Windows.Template.Dll和EAS.Web.Template.Dll)在开发中利于GUI能极大的加速应用开发,GUI模板以源代码的形式向开发人员提供。

属性标记Module

前面的1,2,3节都是基于实现IModule接口的方式来开发插件,下面将提供实现插件的另一种方式,利用.NET的声明编程的方式采用属性标记插件。

我们定义了ModuleAttribute属性:

ModuleAttribute    /// <summary>/// EAS.NET模块插件属性。/// </summary>/// <remarks>/// 提供IModule的标记实现,提供基于属性标记的插件实现。/// </remarks>[AttributeUsage(AttributeTargets.Class)]public class ModuleAttribute : Attribute{private Guid guid = System.Guid.Empty;private string name = string.Empty;private string description = string.Empty;/// <summary>/// 初始化ModuleAttribute对象。/// </summary>/// <param name="guid">模块Guid。</param>/// <param name="name">模块名称。</param>public ModuleAttribute(string guid, string name){this.guid = new Guid(guid);this.name = name;}/// <summary>/// 初始化ModuleAttribute对象。/// </summary>/// <param name="guid">模块Guid。</param>/// <param name="name">模块名称。</param>/// <param name="description">模块说明。</param>public ModuleAttribute(string guid, string name,string description){this.guid = new Guid(guid);this.name = name;this.description = description;}/// <summary>/// 模块Guid。/// </summary>public string Guid{get{return this.guid.ToString();}set{this.guid = new Guid(value);}}/// <summary>/// 模块名称。/// </summary>public string Name{get{return this.name;}set{this.name = value;}}/// <summary>/// 模块说明。/// </summary>public string Description{get{return this.description;}set{this.description = value;}}}

及ModuleRunAttribute/ModuleStartAttribute属性

ModuleStartAttribute    /// <summary>/// 模块入口方法属性。/// </summary>/// <remarks>/// 配合ModuleAttribute实现基于标记的IMoule模块。/// </remarks>[AttributeUsage(AttributeTargets.Method)]public class ModuleStartAttribute : Attribute{/// <summary>/// 初始化ModuleStartAttribute对象。/// </summary>public ModuleStartAttribute(){}}

我们只需要在我们要公共的模块插件的类打上ModuleAttributes标记、在模块的入口调用方法上打上ModuleRunAttribute就可以了,以下为示例:

Hello    /// <summary>/// 基于标记实现的插件。/// </summary>[Module("CB58C5BB-5D15-4a17-802E-341F9F65F35C", "Hello例子", "基于标记的模块实现例子")]public class Hello{/// <summary>/// 入口方法。/// </summary>[ModuleRun]public void Start(){MessageBox.Show("Hello...");}public void Start2(){MessageBox.Show("Hello2...");}}

在以上例子中,我们标记了一个模块插件,他的GUID属性为“CB58C5BB-5D15-4a17-802E-341F9F65F35C”,模块名称为Hello例子,入口方法为Start方法,特别声明一下,Start必须为一公共为参该当,Web模块不需要入口方法。

关于IModule.Run的参数

通常情况运行容器是通过调用IModule接口的Run(params object [] parameters)方法实现功能模块的加载和运行,运行容器通过Run方法向功能模块以下参数。

第一个参数:模块插件的父容器,如果是模块为IModule接口,则这个参数为资源管理平台的主界面(Shell); 如果是模块为IExplorerControl接口,则这个参数为IExplorerControl模块的容器控IExplorerControlContainer实例。

第二个参数:为当前登录到资源管理平台的当前账号(EAS.Explorer.Users.IAccount Account)信息,提供系统当前使用者的信息。

第三个参数:为当前应用程序的会话信息,提供应用程序会话上下文环境,系统会话中包含着数据连接等相关的会话资源,模块程序也可以使用这些。第二个参数与第三个参数是相互的,第二个参数的Session属性就是第三个参数,第三个参数的Client属性就是第二个参数,意思就是说,会话建立在当前账号登录到系统上的这个操作形成的,而会话的客户端正是登前操作者。

功能模块在处理Run(params object [] parameters)方法时,可参考以下代码:

IExplorerControl:

public override void Run(params object[] parameters)

{

ISession session = (EAS.Sessions.ISession)parameters[2];

}

IModule:

public override void Run(params object[] parameters)

{

Form shell = (System.Windows.Forms.Form)parameters[1];

ISession session = (EAS.Sessions.ISession)parameters[2];

}

平台与模块的交互

我们知道,插件开发完成之后要安装、部署在平台中,运行在AgileEAS.NET平台的容器中,插件在运行过程中,如果取得平台的上下文参数,如当前系统的登录账户、数据库连接等一系列的插件运行资源。

在AgileEAS.NET平台的3.5版本之前,插件只有通过实现IModule接口来完成,所以平台与插件的交互也就通过Run方法来完成,Run方法提供了平台的三个参数,详细内容见2.5节。但是在3.5之后,AgileEAS.NET平台增加了更为方便的属性标记实现,对于模块的入口使用ModuleRun标记并且要求开发人员所标记的入口方法为无参方法,这样就无法通过插件入口的调用完成平台的参数传递。

为解决此问题,我们引入了一个上下文的概念,AgileEAS.NET平台上下文环境,在4.0版本后,我们建议即使通过IModule接口实现的模块,也不要使用Run入口方法的参数,转而使用AgileEAS.NET运行容器上下文环境:

EAS.Modularization.Platform.IContainer,提供了会话,上下文环境的定义,他的定义:

IContainer    /// <summary>/// 定义插件的运行容器接口。/// </summary>public interface IContainer{/// <summary>/// 获取应用程序名称。/// </summary>string Name { get;}/// <summary>/// 获取容器上下文环境。/// </summary>IContext Context{get;}/// <summary>/// 获取容器的当前会话。/// </summary>ISession Session{get;}/// <summary>/// 运行模块。/// </summary>/// <param name="module">模块实例。</param>void StartModule(object module);/// <summary>/// 运行模块。/// </summary>/// <param name="module">模块类型。</param>void StartModule(Type module);/// <summary>/// 运行模块。/// </summary>/// <param name="module">模块Guid。</param>void StartModule(Guid module);/// <summary>/// 运行模块。/// </summary>/// <param name="module">模块实例。</param>void StartModule(IModule module);/// <summary>/// 关闭模块。/// </summary>/// <param name="module">模块实例。</param>void CloseModule(object module);/// <summary>/// 关闭当前模块。/// </summary>void CloseModule();/// <summary>/// 关闭模块。/// </summary>/// <param name="module">模块实例。</param>void CloseModule(IModule module);}

通过接口定义我们可以知道,他提供了当前系统的账户、会话、应用程序上下文环境(IOC容器)、会话上下文环境等等。

在当前会话中定义了当前系统的各种会话资源如数据库连接、ORM访问器等等开发基础资料,程序员可以通过

IConnection dncn = Session.Resouces.FindResources(typeof(IConnection))[0] as IConnection;

的方式进行取得各种资源进行业务处理。

插件的调试

在最初的AgileEAS.NET平台版本中,是没有调试环境的,大概在2.0版本中加入了调试环境,WinForm的开发有独立的调试环境,WebForm的开发使用WebForm的运行容器直接调试:

WinForm应用开发中,提供了一个EAS.Develop.Debuger.dll的程序集,由它给我们的插件提供一个模拟的WinForm运行容器,怎么使用这个调试环境呢,首先在应用开发的VS解决方案中,增加一个新的应用程序项目AppStart,引用及其甩依赖的程序集,添加一个Start类并增加如下代码:

   /// <summary>/// 调试器启动类。/// </summary>class AppStart{        /// <summary>/// AgileEAS.NET调试器入口。/// </summary>[STAThread]static void Main() {EAS.Develop.Debuger.Application.Start();}        }

并修改配置文件中的Assembly配置项的值为需要调试的程序集名称:

<ConfigurationItem name="Assembly" value="EAS.Windows.FullExam"/>:

插件调试环境使用与真实运行环境的配置文件,同样的会话、同样的上下文环境,同样的系统会话资源,这一切都由系统配置文件进行配置。

链接

AgileEAS.NET平台开发指南-系列目录

AgileEAS.NET应用开发平台介绍-文章索引

AgileEAS.NET官方网站

敏捷软件工程实验室

QQ群:116773358

转载于:https://www.cnblogs.com/eastjade/archive/2010/09/13/1824708.html

基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET平台开发指南 - 实现插件...相关推荐

  1. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 文章汇总及学习指南...

    一.AgileEAS.NET平台简介 AgileEAS.NET平台是一套应用系统快速开发平台,用于帮助中小软件开发商快速构建自己的企业信息管理类开发团队,以达到节省开发成本.缩短开发时间,快速适应市场 ...

  2. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - ActiveXForm运行容器...

    前面的文章AgileEAS.NET之插件运行容器中对基于WinForm和WebForm技术的容器做了个简单的介绍,接下来,我们介绍一下WinForm和WebForm技术结合的容器ActiveXForm ...

  3. 基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET - 系统架构

    本文是继AgileEAS.NET应用开发平台介绍及AgileEAS.NET之敏捷并行开发方法所做的架构补充,用于阐释AgileEAS.NET平台的架构设计思路. 说起了系统架构,我也无法给出系统架构的 ...

  4. 随笔 - 142 文章 - 0 评论 - 2294 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 权限管理...

    前面我们在AgileEAS.NET之插件接口IModule和AgileEAS.NET之插件运行容器中对模块插件和运行容器都做了介绍,我们知道,在运行容器中,我们要基于模块插件并结合账户/角色进行权限判 ...

  5. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 权限管理

    前面我们在AgileEAS.NET之插件接口IModule和AgileEAS.NET之插件运行容器中对模块插件和运行容器都做了介绍,我们知道,在运行容器中,我们要基于模块插件并结合账户/角色进行权限判 ...

  6. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 插件标记实现

    前面的文章AgileEAS.NET之插件接口IModule对插件的基本契约宝义也就是接口做了一个介绍,本文将提供另一种模块插件的定义,采用属性标记插件. 我们定义了ModuleAttribute属性: ...

  7. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 对象控制反转

    控制反转,即IOC(Inversion of Control),也叫反转模式,也称依赖注入DI(Dependency Injection)模式,关于此概念的解释我在此文不做过讲说明. 对于设计模式类的 ...

  8. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - ActiveXForm在线体验安全设置...

    AvtiveXForm在线演示地址:http://demo.smarteas.net/activexform/,如果是第一次体验演示,请在体验前确保安装了安装.NET2.0 和Activexform客 ...

  9. Admui 源码 是一个基于最新 Web 技术的企业级通用管理系统快速开发框架

    ** QQ194633530 索取源码 ** Admui 是一个基于最新 Web 技术的企业级通用管理系统快速开发框架,可以帮助企业极大的提高工作效率,节省开发成本,提升品牌形象. 您可以 Admui ...

最新文章

  1. 智能车竞赛,AI视觉组赛题浅析
  2. ISE与Modelsim联合仿真关联设置
  3. 训练集(train set) 验证集(validation set) 测试集(test set)
  4. PXE自动化装机(4)
  5. Spring Cloud:connect time out
  6. spingmvc-参数传递
  7. InstallShield 2012 Spring评估试用(1): 支持Windows 8和Windows Server 2012操作系统
  8. POJ 1753 Flip Game 高斯消元
  9. MIPI CSI-2学习
  10. jq判断html加载完成,jquery – 检测页面是否已完成加载
  11. 平流式隔油池计算_隔油池计算方法及图集[参考提供]
  12. 读取SqlServer表名及结构
  13. 关于央行新推数字货币的综述
  14. Linux内核内存压缩技术
  15. TORCHVISION 目标检测微调教程
  16. 百度地图根据经纬度坐标,显示汽车行驶轨迹
  17. CATIA许可证安装,破解文件运行不了直接跳到finish问题
  18. windows mobile数据同步方案
  19. 2015年macbookpro更换电池
  20. 前端怎么从H5调起微信扫描二维码?小程序使用扫码功能.

热门文章

  1. profile 文件含义
  2. windows下GIT使用记录--00准备阶段
  3. m5310模组数据上传至onenet_一张标准的综合布线系统图及图解注释,带你看懂网络摄像机的数据如何最终上传至核心交换机...
  4. leetcode算法题--旋转链表
  5. matlab中libsvm 3.11,libsvm-3.11(matlab)
  6. eja变送器故障代码al01_EJA系列差压变送器的使用及故障分析
  7. 不同编程语言在发生stackoverflow之前支持的调用栈最大嵌套层数
  8. python Unicode转ascii码的一种方法
  9. Cocos2D粒子发射器的纹理
  10. chrome浏览器模拟手机 地理定位