ERP/MIS开发 开发LLBL Gen 插件(Plun-in) Implementing a plug-in
以LLBL Gen作为ORM的首选开发工具,在经历几个项目之后,对它的认识又有了新的高度。一方面要对Query API熟练于心,这样写查询语句才会得心应手,另一方面,也在尝试从ORM的实现,源代码分析,扩展方面来了解这个ORM工具,以便在项目出现救急的问题时可以得心应手,临危不乱。    
    
这篇文章介绍LLBL Gen SDK中的内容,关于如何开发LLBL Gen插件的内容。这个Entity Visualizer插件是来源于ORM设计时,同时也想查看数据表的内容,于是产生了这个想法。功能好比.NET内置的Data Set Visualizer. 运行效果 
从Table中选择一个表,下面的datagrid会显示这个表的所有数据。    
众所周知,开发插件最主要的工作是熟悉软件留下来的接口,以前自己设计插件框架来给别人开发插件,现在要反过来,用别人设计好的框架,来为之开发插件,所以,如果有开发过插件框架,可以少走一些弯路。     
LLBL Gen的插件放在安装目录的Plugins目录中,也可以通过修改LLBLGenPro.exe.config配置文件中的选项来修改     
<!-- Specification of the root folder where LLBLGen Pro will search for plugin assemblies -->     
<!-- This path is always relative to the application folder. -->     
<add key="pluginsRootFolder" value="Plugins"/>
插件以.NET语言设计编码,多个插件可以放到一个程序集中,也可以分开为多个程序集。    
    
插件运行于LLBL Gen 容器中,有两种类型的用户界面接口,IPluginWindow用于独立的窗口,如下图,一个tab选项卡窗口,我们的插件dock在这个tab页面中,另一种是以控件的形式运行于指定的界面中,如下图
 
     
如果要设计这种界面类型的插件,请派生于IPluginConfigurationControl。     
启动Visual Studio,创建一个类库项目,到LLBL Gen的安装目录中,查找并添加对以下程序集的引用     
 
添加一个新类型,派生于PluginBase。首先要重写Describe方法,这个方法用来显示我们插件的描述信息。    
public override PluginDescription Describe()     
{     
           PluginDescription toReturn = base.Describe(); 
           toReturn.Build = _build;    
           toReturn.Description = "Display the data of the specific mapping entity";     
           toReturn.Id = new Guid("{1CCEEDD1-AD19-49c9-B711-BE2087D0F94A}");     
           toReturn.Name = "Entity Visualizer Plug-in";     
           toReturn.ShowProgressViewerDuringExecution = false;     
           toReturn.TargetType = PluginTargetType.Entity;     
           //toReturn.TypeOfPlugin = PluginType.SingleElementPlugin;     
           toReturn.TypeOfPlugin = PluginType.DirectRun;     
           toReturn.Vendor = "EPN Solution";     
           toReturn.Version = _version;     
           toReturn.SurpressProjectExplorerRedraw = false;     
           return toReturn;     
}
ShowProgressViewerDuringExecution 用于说明,在执行插件功能时,是否要显示进度条。    
来看一个TargetType 的类型,就是插件应用于哪种对象之上,比如项目,类型视图,实体,存储过程等。
[Flags]    
public enum PluginTargetType     
{     
        None = 0,     
        Entity = 1,     
        TypedList = 2,     
        TypedView = 4,     
        ActionSPCall = 8,     
        RetrievalSPCall = 16,     
        Project = 32,     
        Object = 64,     
}     
我的Entity Visualizder插件是要显示表的数据,要应用的TargetType 那就是Entity.     
TypeOfPlugin是指插件类型,这个值会决定插件要应用的范围,来看它的值     
public enum PluginType     
{     
      SingleElementPlugin = 0,    //一个元素     
      MultiElementPlugin = 1,      //多个元素的插件     
      SingleAndMultiElementPlugin = 2,   //单个或多个元素的插件     
      DirectRun = 3,                //直接运行     
      System = 4,                   //系统     
}     
Entity Visualizder插件是独立的可以直接运行的,所以它的TypeOfPlugin =DirectRun。     
如果 TypeOfPlugin =SingleElementPlugin 时,它的界面如下      
 
运行插件的容器控件,会自动加载Target element:Entity:Customer,这是框架自动生成的。当TypeOfPlugin =MultiElementPlugin 时,它的界面如下  
出现了2个tab,第一个tab是选择要应用的对象,可以多选,第二个tab和上面是一样的界面。    
SurpressProjectExplorerRedraw 属性用来表示,当插件运行时,主界面是否要挂起,请对比下面的两张图
第二张图
区别看出来了,Project Explorer在SurpressProjectExplorerRedraw =true时,会像第二张图那样,把其中的内容藏起,以进行重绘,当它的值为false时,Project Explorer中的内容仍然会显示。    
    
为插件添加控件,前面说过,要在独立的tab窗体中运行插件,请添加新窗体并且派生于IPluginWindow     
public partial class EntityVisualizerControl : Form, IPluginWindow     
如果是在标准的容器界面中运行,请添加Windows控件,并派生于IPluginConfigurationControl     
public class AssignTypeConvertersControl : UserControl, IPluginConfigurationControl
解释一下,标准的容器界面,如上图,有Target element标签,和两个按钮Run!/Cancel,这就是标准的容器界面。    
    
如果是控件,请添加如下的代码,以供标准容器界面加载些控件     
public override System.Windows.Forms.Control GetConfigurationControl()     
{ _control = new AddCustomPropertiesConfigurationControl();     
   return _control;     
}     
最后的一个步骤是,添加插件的运行代码,就是插件运行时,到底要做什么,重写Execute方法     
public override void Execute()     
{           
EntityVisualizerControl _control = new EntityVisualizerControl(base.ProjectToTarget.ConnectionString, this);     
     base.OpenDockedWindow(_control);     
}     
这里是打开独立的tab页面窗体,如果是控件,通常会用写样写     
public override void Execute()     
        {     
            _typeConversionsSelected = _control.SelectedTypeConversions; 
            // 2 main tasks: entity, typed view    
            base.ProgressTaskInit(2); 
            base.ProgressTaskStart("Processing entities");    
            base.ProgressSubtaskInit(base.Entities.Count);     
            foreach(EntityDefinition entity  in base.Entities)     
            {
}
}    
_control是我们设计的控件,它接受用户输入后,当用户点击Run!按钮时,返回值给插件容器,执行Execute方法。     
这里会用到一些框架传回来的变量,比如base.Entities,是当前选择应用插件的实体元素,base.TypedViews视图。
   
讲了这么多,都是讲如何与LLBL Gen的插件框架打交道,插件的功能还没有说明。插件在运行时,根据Project的连接字符串,连接到数据库中,应用下面的SQL语句,读取所有的表名     
select name from sysobjects where type='U'     
订阅cmbTables的SelectedIndexChanged事件,重新加载数据表grid中。     
    
如果对源代码感兴趣,请到epn.codeplex.com的Source Code中下载最新的源代码。

