• wf框架编程(设计器部分)


     

    五、工作流设计器

    1 Net设计器基础框架

    .net设计器基础框架所在的命名空间是System.ComponentModel.Design,而wfasp.netwin 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

    AddToolboxEntrieslistbox.Items.Add(new SelfHostToolboxItem(entry)

    CategoryNames:工具箱类别属性

    AddCreator:

    其中的WorkflowDesignerControl我觉得是Mediator模式的应用

    ü         选取服务

    相关assembliesCCU的容器:TypeProvider

    大家可以downSharpDevelop的源代码看看,有本书专门介绍这个的。

    2 WF设计器

    WF设计器的实现思路主要是每个Activity对应的ActivityDesigner和驻留环境(Designer Surface),这也为我们实现基于WebWF设计器提供了思路,就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实现

                  通过ProvidePropertyAttributePropertyGrid关联

                  IExtenderProvider.CanExtend作为是否使用属性的依据,如果为truePropertyGrid控件会查找extender类中的Get<PropertyName>,Set<PropertyName>方法,实现和Acivity属性的交互。

    Wf还没有开源,猜测这里这里使用AOP代码织入并使用了Template模式。

           3.Activity的声明使用自定义的ActivityDesignerDesigner(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方式实现DesignerGlyphGetBoundsOnPaint方法

           3.对于简单活动,直接override实现ActivityDesignerOnLayoutSize,OnPaint方法

                         OnLayoutSize:返回大小

                         OnPaint:实现了一些必要的绘图功能

                         GetBounds:返回代表图形边界的矩形

    修改设计器布局

           重载Acitivity DesignerOnLayoutSizeOnLayoutPosition

           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.是一个服务容器,提供取消、剪切板功能和其它活动设计器需要的功能。

    事务管理

    组件管理:CreateComponentGetDesignerGetType

    设计器的加载和管理

                 // 摘要:

            //     在激活此设计器时发生。

            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)等领域描述语言。序列化为什么格式,可以在AcitivityAttribute中指定。

    TypeCodeDomSerializer:序列化为代码

    WorkflowMarkupSerializer:序列化为XAML文件


    设计器序列化使用的类库

    4 代码生成

    如果流程中存在Code Activity,那么还需要设计器能动态生成代码。如果指定了TypeCodeDomSerializer,也需要动态代码生成,最后整个WF活动才能通过编译成为.Net下的Assembly

    活动代码生成在验证后调用C#代码编译前执行,活动代码生成实际上是给了一个使用CodeDOM生成代码文件的机会。代码生成下次说吧。

  • 相关阅读:
    php1
    element ui
    webpack
    vue-router
    vue实例相关2
    vue实例相关
    js笔记2
    js笔记
    不找工作,你的简历也要更新!
    除了做测试,我们还能做些什么呢?
  • 原文地址:https://www.cnblogs.com/lodestar/p/1188655.html
Copyright © 2020-2023  润新知