以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中。