以LLBL Gen作为ORM的首选开发工具,在经历几个项目之后,对它的认识又有了新的高度。一方面要对Query API熟练于心,这样写查询语句才会得心应手,另一方面,也在尝试从ORM的实现,源代码分析,扩展方面来了解这个ORM工具,以便在项目出现救急的问题时可以得心应手,临危不乱。

这篇文章介绍LLBL Gen SDK中的内容,关于如何开发LLBL Gen插件的内容。这个Entity Visualizer插件是来源于ORM设计时,同时也想查看数据表的内容,于是产生了这个想法。功能好比.NET内置的Data Set Visualizer. 运行效果

image

从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页面中,另一种是以控件的形式运行于指定的界面中,如下图

image
如果要设计这种界面类型的插件,请派生于IPluginConfigurationControl。

启动Visual Studio,创建一个类库项目,到LLBL Gen的安装目录中,查找并添加对以下程序集的引用
image

添加一个新类型,派生于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 时,它的界面如下
image

运行插件的容器控件,会自动加载Target element:Entity:Customer,这是框架自动生成的。当TypeOfPlugin =MultiElementPlugin 时,它的界面如下 
image

出现了2个tab,第一个tab是选择要应用的对象,可以多选,第二个tab和上面是一样的界面。
SurpressProjectExplorerRedraw 属性用来表示,当插件运行时,主界面是否要挂起,请对比下面的两张图image

第二张图

image

区别看出来了,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中下载最新的源代码。

作者: James Li 发表于 2011-08-26 11:30 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"