1 Net設計器基礎框架
.net設計器基礎框架所在的命名空間是System.ComponentModel.Design,而wf、asp.net、win from這三種設計器架構都是建立在.Net本身提供的基礎框架之上。
wf設計器框架所在的命名空間是System.Workflow.ComponentModel.Design,相關類都在這個NameSpace裡面。在研究wf設計器之前,我們先看看Winform設計器。對Winform設計器的研究,對WF設計器的理解很有幫助。
1.1 Winform設計器設計:
曾經研究過幾天SharpDevelop,一個免費開源的IDE開發環境,並且有類似eclipse的插件思想。在這個開源IDE裡面有比較完整的Winform設計器實現。Winform
IDE主要依靠下面幾個接口和類實現。只要實現了相關的接口和抽象,.Net框架會幫助我們實現Winform設計器。很像模板方法。相應的接口和類為:
Winform設計器結構
ü DesingerHost:
1.服務管理:服務容器和服務提供者
2.組件管理和事務管理
ü ISite:
綁定組件和容器,DesignerHost中所有的服務都可以通過ISite(GetService)得到
ü IServiceProvide
ü IDesinger
提供定制服務,設計期在組件的上下文菜單中添加菜單命令,添加的組件實現操作
Initialize方法中與ICompont關聯
工具箱實現:
ü IToolboxService
工具箱服務,主要目的是存儲ToolboxItem
如何填充工具箱?
要使用ToolboxItemFilterAttribute
AddToolboxEntries:listbox.Items.Add(new SelfHostToolboxItem(entry)
CategoryNames:工具箱類別屬性
AddCreator:
其中的WorkflowDesignerControl我覺得是Mediator模式的應用
ü 選取服務
相關assemblies和CCU的容器:TypeProvider
大家可以down下SharpDevelop的源代碼看看,有本書專門介紹這個的。
2 WF設計器
WF設計器的實現思路主要是每個Activity對應的ActivityDesigner和駐留環境(Designer Surface),這也為我們實現基於Web的WF設計器提供了思路,就winform環境和webform環境比較,AcitivityDesinger是不變的,變化的是駐留環境。很長時間沒有接觸WF了,這裡討論的環境是Winfrom下的,以後有機會做的Web環境下再整理吧。
Wf設計器結構
2.1 Activity Designer
Activity關於默認的DesignerAttribute聲明是Designer(typeof(ActivityDesigner), typeof(IDesigner);Designer(typeof(ActivityDesigner), typeof(IRootDesigner)
我們如果實現自定義的Acitivity,一般從Activity繼承就可以了,不需要重新寫。由於ActivityDesigner的設計表現為簡單矩形,所以我們看到的活動都是簡單矩形的樣子,當然我們也可以修改的很漂亮。對應復合活動,如圖,從CompositeActivityDesigner上繼承下來Desinger有好幾個,都有自己的設計表現,其中:ParallelActivityDesigner表現為所有子活動並行;SequenceDesigner表現是自動以順序方式呈現子活動。
如果是特殊的復合活動,可能需要自己實現Desinger。這裡覺的例子是wf本質論上的,大家也可以比較書看一下,電子書是可以免費下載的。例子中要實現自定義的PrioritizedInterleave,設計表現是需要在設計器上表現出優先級關系,由於現有類庫缺乏支持,所以就需要自己實現特點的Acitivity Designer.
如何實現自定義ActivityDesigner
PrioritizedInterleaveDesigner例子中,設計意圖是點自活動可以在PropertyGrid中設置Priority屬性,根據Priority值,子活動位於不特點位置
可以通過PropertyGrid設置屬性
1.IExtenderListService中加入特定IExtenderProvider。見類圖。
2.特定IExtenderProvider實現
通過ProvidePropertyAttribute和PropertyGrid關聯
IExtenderProvider.CanExtend作為是否使用屬性的依據,如果為true,PropertyGrid控件會查找extender類中的Get<PropertyName>,Set<PropertyName>方法,實現和Acivity屬性的交互。
Wf還沒有開源,猜測這裡這裡使用AOP代碼織入並使用了Template模式。
3.Activity的聲明使用自定義的ActivityDesigner。Designer(typeof(自定義ActivityDesigner), typeof(IDesigner)
例子中PrioritizedInterleaveDesigner繼承自CompositeActivityDesigne,所以對PrioritizedInterleave的聲明,實際上對整個復合活動的聲明
CompositeActivityDesigner.ContainedDesigners
右鍵菜單修改屬性
1.實現IDesignerVerbProvider接口
2.初始化活動的時候IDesignerVerbProviderService.AddVerbProvider(IDesignerVerbProvider);
3.接口實現
通過ActivityDesignerVerb.Properties得到Activity
針對這個Activity get並修改後Set
4.PerformLayout使修改生效
修改設計器圖形(復合活動和基礎活動都可以修改)
1.對於復合活動override Glyphs方法,得到ActivityDesignerGlyphCollection
ActivityDesignerGlyphCollection.Add(DesignerGlyph);
2.DesignerGlyph的實現
override方式實現DesignerGlyph的GetBounds和OnPaint方法
3.對於簡單活動,直接override實現ActivityDesigner的OnLayoutSize,OnPaint方法
OnLayoutSize:返回大小
OnPaint:實現了一些必要的繪圖功能
GetBounds:返回代表圖形邊界的矩形
修改設計器布局
重載Acitivity Designer的OnLayoutSize和OnLayoutPosition
OnLayoutSize返回設計器的合計大小尺寸,OnLayoutPosition計算出子活動的偏移。
設計器主題
1.實現特定的ActivityDesignerTheme
2.再通過ActivityDesignerThemeAttribute注入
3.ActivityDesigner.OnPaint中可以調用Theme
工具箱
默認是通過ToolboxItemAttribute指向ActivityToolboxItem。
如果有特殊需求,例如在托拽的時候要實現復合控件可以繼承ActivityToolboxItem,並在CreateComponentsCore中實現
這時候ToolboxItemAttribute指向自定義的ActivityToolboxItem
使用ToolboxBitmapAttribute可以在工具箱實現自定義視圖
2.2 駐留設計器
Designer Surface:職責是管理Designer Host,管理與用戶交互(得到view,得到host,異步加載Designer加載器)
Designer Host的職責
1.管理IComponent和相關的IDesigner之間的交互;
2.是一個服務容器,提供取消、剪切板功能和其它活動設計器需要的功能。
事務管理
組件管理:CreateComponent,GetDesigner,GetType
設計器的加載和管理
// 摘要:
// 在激活此設計器時發生。
event EventHandler Activated;
//
// 摘要:
// 在停用此設計器時發生。
event EventHandler Deactivated;
//
// 摘要:
// 在此設計器加載完文檔時發生。
event EventHandler LoadComplete;
Designer View的職責
1.呈現各種ActivityDesigner,向各個ActivityDesigner發送消息
2.窗體管理、命令路由、窗體滾動、托放、滾動、布局、打印和打印預覽
ISite的職責是綁定組件和容器,DesignerHost中所有的服務都可以通過ISite(GetService)得到
IServiceContainer是服務容器,可以形成樹,promote參數true,服務的添加和刪除操作會提交給基容器,這些接口的實現思路和winfrom的設計器實現思路非常像。
2 設計器序列化
像VS一樣,流程設計出來必須要持久化保存,下次使用或者修改的時候通過反序列化操作,我們可以得到曾經設計的流程。
我們可以將活動樹序列化為XAML或者代碼(默認),甚至可以序列化為(BPEL,DSL)等領域描述語言。序列化為什麼格式,可以在Acitivity的Attribute中指定。
TypeCodeDomSerializer:序列化為代碼
WorkflowMarkupSerializer:序列化為XAML文件
設計器序列化使用的類庫
4 代碼生成
如果流程中存在Code Activity,那麼還需要設計器能動態生成代碼。如果指定了TypeCodeDomSerializer,也需要動態代碼生成,最後整個WF活動才能通過編譯成為.Net下的Assembly
活動代碼生成在驗證後調用C#代碼編譯前執行,活動代碼生成實際上是給了一個使用CodeDOM生成代碼文件的機會。代碼生成下次說吧。