zoukankan      html  css  js  c++  java
  • Composite UI Application Block学习笔记之Event Broker[转载]

    Composite UI Application Block着重于将应用逻辑和界面分开,让应用系统具备更清晰的结构,更强的扩展性、可移植性。在曹严明先生的讲座中,提及到了关于应用CAB开发的几个指导性原则:

    • 将 views (SmartPart)设计为独立于 controllers 的单元
    • 共享模块状态
    • 共享基础服务
    • 封装用例 - 重用
    • 降低模块间的依赖性
    • 尽量使用 events, services, and interfaces

         我在学习的过程中也理解到以上原则的重要性和指导性,在我学习模块状态和Event Broker的过程中,也将上述部分原则做了特意的应用。那么我们还是通过一个实例来学习Event Broker和这些原则。

    一、文中有关术语

        下面这些术语是CAB中常用到的,以下的解释仅是我个人的理解,不敢保证完全准确,园子里的朋友请指教。

        Event Broker:事件代理,通过事件源和订阅事件源来达成对象之间的协作。

        Event Publisher: 事件发布者,在CAB里是一个用属性EventPublication修饰的事件对象,提供特定的URL给Event Subscriber订阅。

        Event Subscriber: 事件订阅者,在CAB里是一个用属性EventSubscription修饰的方法,根据修饰提供的URL自动寻找事件发布者。Publisher和Subscriber之间由主题(由URL决定),消息(特定的 EventArgs),事件域(来确定是全局事件还是局部事件)来达成一致。其实这也是观察者模式的具体实现。

        WorkItem:代表一个用例,也可以看成是某个业务完成的过程,它包含在WorkSpace中,服务于Service Agents(服务代理),并且加载其状态。创建其他组件或者视图,CAB来创建controller.组件共享WorkItem的状态,并且可以通过状态来控制用例的生命周期。

        WorkItem State:状态,实际上是把业务对象或者业务对象的属性,通过WorkItem State共享出来,方便其他业务对象或者视图访问。

    二、体验Event Broker应用

        讲了这么多有关Event Broker的理论和概念了,我们还是通过一个简单的例子来体验Event Broker这种实现模式的优越性吧。

    1.应用场景

         平时我们在开发过程中碰到最多的例子大概就是,一个业务对象数据集要通过dataGrip,ListBox甚至Chart控件等将其表现出来了。今天,我在学习笔记里也以这个例子来阐述Event Broker,在开发中带来的好处。

        场景是这样的:某人事信息管理软件要求输入人员的性别和姓名,并且能将输入的人员在通过表格和列表框的形式表现出来,同时录入人员的男女比例要能适时的通过饼图显示。

    2.分析场景,确定开发模式

    a.需求中涉及到的唯一业务对象是人员,具有性别和姓名两个属性。为了简单起见我们可以建立数据集来代替该对象。

    b.需求要求能输入姓名、性别,我们可以用文本框和下拉框来完成信息采集。

    c.需求要求人员信息,通过表格,ListBox和饼图来显示,我们可以在VS2005中用DataGrid、ListBox、ReportView来实现此项需求。

    d.由于业务对象单一,而信息表现却又多个,适合用观察者模式进行开发。我们便采用CAB中的Event Broker作为重要的实现手段。

    3.建立应用程序

    第一步:新建项目

         启动VS2005,新建Windows Application,添加以下引用:

    Microsoft.Practices.CompositeUI

    Microsoft.Practices.CompositeUI.WinForms

    Microsoft.Practices.ObjectBuiler

    Microsoft.Practices.CompositeUI.Utility

    Microsoft.Practices.CompositeUI.WinForms

    第二步:建立数据集

        右击项目文件夹,添加新项,选择数据集,建立用户信息数据集(没有通过代码创建,主要是为了设计报表方便)。为数据集添加DataTable1的表,为DataTable1添加列Sex和Name。

    第三步:绘制界面

         在VS2005默认生成的Form1上建立饼图、DataGrid、ListBox和相关相关控件,具体操作我在此略过,最终效果如下图:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

    第四步:修改入口程序

        为了让程序能使用CAB,我们必须修改程序的入口类Program.cs。最终修改结果如下:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗using System;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Collections.Generic;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Windows.Forms;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Data;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using Microsoft.Practices.CompositeUI;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using Microsoft.Practices.CompositeUI.WinForms;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    namespace TestReport
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    class Program : FormShellApplication<WorkItem, Form1>
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    /**//// <summary>
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    /// The main entry point for the application.
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    /// </summary>

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗[STAThread]
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    static void Main()
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    new Program().Run();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    protected override void BeforeShellCreated()
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    base.BeforeShellCreated();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    //共享状态,通过"dataset"关键字访问
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
      RootWorkItem.State["dataset"= new DataSet1();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

       需要注意的是:为了能使用WorkItem的State,在Shell创建之前必须给共享的状态赋初值,否则在访问该状态时将出现状态没有创建实例的运行时错误。本例中就是加入以下代码:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗protected override void BeforeShellCreated()
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    base.BeforeShellCreated();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  RootWorkItem.State[
    "dataset"= new DataSet1();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    第五步:建立controller

    建立controller负责用户信息添加,建立事件源。添加类文件,命名为Form1Controller,将该类从controller继承。如下代码所示:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗using System;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Collections.Generic;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Text;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using Microsoft.Practices.CompositeUI;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using Microsoft.Practices.CompositeUI.EventBroker;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using Microsoft.Practices.CompositeUI.Utility;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    using System.Data;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    namespace TestReport
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗 
    public class Form1Controller: Controller
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗 
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  }

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

    在controller中公布一个事件发布者,通过"topic://TestReport/DataRowAdded"来标识Publisher,默认的事件域为全局。也可以通过PublicationScope枚举来设置事件的作用域。事件作用域有以下三种:

    PublicationScope.WorkItem :仅作用于引发当前发布的WorkItem实例

    PublicationScope.Global:作用于引发当前发布的WorkItem所有实例

    PublicationScope.Descendants:仅作用于引发当前发布的WorkItem实例,以及该WorkItem的任何级别的子WorkItem实例。

    本例通过以下代码发布事件:

    [EventPublication("topic://TestReport/DataRowAdded")]
    public event EventHandler<DictionaryEventArgs> DataRowAdded;

    controller中主要来实现业务逻辑,于是我们需要添加一个方法AddNewRow(int sex, string name),用来实现人员信息的添加,代码如下:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗private DataSet1 ctldataset;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗 
    //controller的AddNewRow方法,引发事件DataRowAdded
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    public void AddNewRow(int sex, string name)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    if (DataRowAdded != null)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  DataRow myRow 
    = ctldataset.DataTable1.NewRow();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  myRow[
    0= sex;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  myRow[
    1= name;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  ctldataset.DataTable1.Rows.Add(myRow);
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  ctldataset.AcceptChanges();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  DictionaryEventArgs args 
    = new DictionaryEventArgs();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  args.Data[
    "dataRow"= myRow;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  DataRowAdded(
    this, args);
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  State.RaiseStateChanged(
    "dataset", myRow);
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

       大家请注意下面代码,其实是定义了一个DictionaryEventArgs参数,并且将当前添加的行对象作为该参数的值。当DataTable1中行添加后,我们引发事件DataRowAdded(this, args)。  此时,事件源被触发了,订阅者就可以接收到该事件广播了。

    DictionaryEventArgs args = new DictionaryEventArgs();
    args.Data["dataRow"] = myRow;
    DataRowAdded(this, args);

       到此,我们已经完成了事件源的创建和发布,为了达到演示的效果,我们还需要实现共享WorkItem State来广播事件。如以下代码:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗[State("dataset")]
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    public DataSet1 CtlDataSet 
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    set 
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  ctldataset 
    = value;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    public new State State
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    get Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗return base.State; }
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗


        我们注意到[State("dataset")]这行代码,它是用来表示WorkItem的属性CtlDataSet,将通过[State("dataset")]共享出去,同时当CtlDataSet改变时,通过代码State.RaiseStateChanged("dataset", myRow),来引发状态改变事件,其他地方就可以得到该事件的委托。

    第六步:整合界面和controller
        我们回到Form1.cs编辑代码。为了让界面和controller和界面结合,我们将controller作为界面对象的一个属性,用以下代码实现:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗//定义该窗体相关的Controller
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    private Form1Controller controller;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    //将该窗体相关的Controller标记为自动创建实例
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    [CreateNew]
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    public Form1Controller Controller
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗  
    set Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{ controller = value; }
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

       为添加按钮加入代码,实现添加一个人员信息:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗private void btn_AddToTable_Click(object sender, EventArgs e)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    if((this.textBox1.Text.Trim().Length >0))
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗 
    this.controller.AddNewRow(this.cmbSex.SelectedIndex, this.textBox1.Text.Trim());
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

       还有为了让Grid和report view能够同步显示人员信息,我们需要订阅由topic://TestReport/DataRowAdded标示的事件:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗[EventSubscription("topic://TestReport/DataRowAdded")]
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    public void OnCustomerAdded(object sender, DictionaryEventArgs e)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.dataGridView1.DataSource = ((DataSet1)this.controller.State["dataset"]).DataTable1.DefaultView;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.DataTable1BindingSource.DataSource = ((DataSet1)this.controller.State["dataset"]).DataTable1.DefaultView;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.reportViewer1.RefreshReport();
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

       这样每添加一个人员,Grid和Reoport View就能适时更新自身表现了,这就是Event Broker的实现方式,简单并且简洁。前面我们还提到了通过共享状态来实现视图和业务对象的关联,在本例中也提供实现。

    首先,在FormLoad事件中订阅StateChanged事件:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗private void Form1_Load(object sender, EventArgs e)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.controller.State.StateChanged += new EventHandler<StateChangedEventArgs>(State_Changed);
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

    然后,通过代码更新List状态:

    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗void State_Changed(object sender, StateChangedEventArgs e)
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗{
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.listBox1.DataSource = ((DataSet1)this.controller.State["dataset"]).DataTable1.DefaultView;
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.listBox1.DisplayMember = "Name";
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗
    this.listBox1.ValueMember = "Name";
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗}

    好了,到此我们的例程已经大功告成,最终的运行效果如下图:
    Composite UI Application Block学习笔记之Event Broker[转载]  - sunbird - 阿波罗

    本文相关代码通过此连接下载:/Files/hyphappy/TestReport.rar

  • 相关阅读:
    使用Windbg调试.Net应用程序 [转]
    jquery的$.extend和$.fn.extend作用及区别
    java获取ip
    在IDEA中使用MyBatis Generator逆向工程生成代码
    github结合TortoiseGit使用sshkey,无需输入账号和密码
    Mapped Statements collection does not contain value for com.xxxx.dao.impl.AreaDAOImpl.findByCode
    idea设置tomcat虚拟路径的两种方法
    spring MVC中传递的参数对象中包含list的情况
    PowerDsigner 16逆向工程导入mysql
    [C++]Qt文本操作(按行读写)
  • 原文地址:https://www.cnblogs.com/lglruirui/p/1778122.html
Copyright © 2011-2022 走看看