日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Composite UI Application Block學(xué)習(xí)筆記之Even

系統(tǒng) 2041 0

???? Composite UI Application Block著重于將應(yīng)用邏輯和界面分開(kāi),讓應(yīng)用系統(tǒng)具備更清晰的結(jié)構(gòu),更強(qiáng)的擴(kuò)展性、可移植性。在曹嚴(yán)明先生的講座中,提及到了關(guān)于應(yīng)用CAB開(kāi)發(fā)的幾個(gè)指導(dǎo)性原則:

  • 將 views (SmartPart)設(shè)計(jì)為獨(dú)立于 controllers 的單元
  • 共享模塊狀態(tài)
  • 共享基礎(chǔ)服務(wù)
  • 封裝用例 - 重用
  • 降低模塊間的依賴性
  • 盡量使用 events, services, and interfaces

???? 我在學(xué)習(xí)的過(guò)程中也理解到以上原則的重要性和指導(dǎo)性,在我學(xué)習(xí)模塊狀態(tài)和Event Broker的過(guò)程中,也將上述部分原則做了特意的應(yīng)用。那么我們還是通過(guò)一個(gè)實(shí)例來(lái)學(xué)習(xí)Event Broker和這些原則。

一、文中有關(guān)術(shù)語(yǔ)

??? 下面這些術(shù)語(yǔ)是CAB中常用到的,以下的解釋僅是我個(gè)人的理解,不敢保證完全準(zhǔn)確,園子里的朋友請(qǐng)指教。

??? Event Broker:事件代理,通過(guò)事件源和訂閱事件源來(lái)達(dá)成對(duì)象之間的協(xié)作。

??? Event Publisher: 事件發(fā)布者,在CAB里是一個(gè)用屬性EventPublication修飾的事件對(duì)象,提供特定的URL給Event Subscriber訂閱。

??? Event Subscriber: 事件訂閱者,在CAB里是一個(gè)用屬性EventSubscription修飾的方法,根據(jù)修飾提供的URL自動(dòng)尋找事件發(fā)布者。Publisher和Subscriber之間由主題(由URL決定),消息(特定的 EventArgs),事件域(來(lái)確定是全局事件還是局部事件)來(lái)達(dá)成一致。其實(shí)這也是觀察者模式的具體實(shí)現(xiàn)。

??? WorkItem:代表一個(gè)用例,也可以看成是某個(gè)業(yè)務(wù)完成的過(guò)程,它包含在WorkSpace中,服務(wù)于Service Agents(服務(wù)代理),并且加載其狀態(tài)。創(chuàng)建其他組件或者視圖,CAB來(lái)創(chuàng)建controller.組件共享WorkItem的狀態(tài),并且可以通過(guò)狀態(tài)來(lái)控制用例的生命周期。

??? WorkItem State:狀態(tài),實(shí)際上是把業(yè)務(wù)對(duì)象或者業(yè)務(wù)對(duì)象的屬性,通過(guò)WorkItem State共享出來(lái),方便其他業(yè)務(wù)對(duì)象或者視圖訪問(wèn)。

二、體驗(yàn)Event Broker應(yīng)用

??? 講了這么多有關(guān)Event Broker的理論和概念了,我們還是通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)體驗(yàn)Event Broker這種實(shí)現(xiàn)模式的優(yōu)越性吧。

1.應(yīng)用場(chǎng)景

???? 平時(shí)我們?cè)陂_(kāi)發(fā)過(guò)程中碰到最多的例子大概就是,一個(gè)業(yè)務(wù)對(duì)象數(shù)據(jù)集要通過(guò)dataGrip,ListBox甚至Chart控件等將其表現(xiàn)出來(lái)了。今天,我在學(xué)習(xí)筆記里也以這個(gè)例子來(lái)闡述Event Broker,在開(kāi)發(fā)中帶來(lái)的好處。

??? 場(chǎng)景是這樣的:某人事信息管理軟件要求輸入人員的性別和姓名,并且能將輸入的人員在通過(guò)表格和列表框的形式表現(xiàn)出來(lái),同時(shí)錄入人員的男女比例要能適時(shí)的通過(guò)餅圖顯示。

2.分析場(chǎng)景,確定開(kāi)發(fā)模式

a.需求中涉及到的唯一業(yè)務(wù)對(duì)象是人員,具有性別和姓名兩個(gè)屬性。為了簡(jiǎn)單起見(jiàn)我們可以建立數(shù)據(jù)集來(lái)代替該對(duì)象。

b.需求要求能輸入姓名、性別,我們可以用文本框和下拉框來(lái)完成信息采集。

c.需求要求人員信息,通過(guò)表格,ListBox和餅圖來(lái)顯示,我們可以在VS2005中用DataGrid、ListBox、ReportView來(lái)實(shí)現(xiàn)此項(xiàng)需求。

d.由于業(yè)務(wù)對(duì)象單一,而信息表現(xiàn)卻又多個(gè),適合用觀察者模式進(jìn)行開(kāi)發(fā)。我們便采用CAB中的Event Broker作為重要的實(shí)現(xiàn)手段。

3.建立應(yīng)用程序

第一步:新建項(xiàng)目

???? 啟動(dòng)VS2005,新建Windows Application,添加以下引用:

Microsoft.Practices.CompositeUI

Microsoft.Practices.CompositeUI.WinForms

Microsoft.Practices.ObjectBuiler

Microsoft.Practices.CompositeUI.Utility

Microsoft.Practices.CompositeUI.WinForms

第二步:建立數(shù)據(jù)集

??? 右擊項(xiàng)目文件夾,添加新項(xiàng),選擇數(shù)據(jù)集,建立用戶信息數(shù)據(jù)集(沒(méi)有通過(guò)代碼創(chuàng)建,主要是為了設(shè)計(jì)報(bào)表方便)。為數(shù)據(jù)集添加DataTable1的表,為DataTable1添加列Sex和Name。

第三步:繪制界面

???? 在VS2005默認(rèn)生成的Form1上建立餅圖、DataGrid、ListBox和相關(guān)相關(guān)控件,具體操作我在此略過(guò),最終效果如下圖:

Composite UI Application Block學(xué)習(xí)筆記之Event Broker_第1張圖片

第四步:修改入口程序

??? 為了讓程序能使用CAB,我們必須修改程序的入口類Program.cs。最終修改結(jié)果如下:
???

using ?System;
using ?System.Collections.Generic;
using ?System.Windows.Forms;
using ?System.Data;
using ?Microsoft.Practices.CompositeUI;
using ?Microsoft.Practices.CompositeUI.WinForms;

namespace ?TestReport
{
??
class ?Program?:?FormShellApplication < WorkItem,?Form1 >
{
/// ? <summary>
/// ?The?main?entry?point?for?the?application.
/// ? </summary>

[STAThread]
static ? void ?Main()
{
??
new ?Program().Run();
}


protected ? override ? void ?BeforeShellCreated()
{
??
base .BeforeShellCreated();
// 共享狀態(tài),通過(guò)"dataset"關(guān)鍵字訪問(wèn)
??RootWorkItem.State[ " dataset " ]? = ? new ?DataSet1();
}

}

}


?? 需要注意的是:為了能使用WorkItem的State,在Shell創(chuàng)建之前必須給共享的狀態(tài)賦初值,否則在訪問(wèn)該狀態(tài)時(shí)將出現(xiàn)狀態(tài)沒(méi)有創(chuàng)建實(shí)例的運(yùn)行時(shí)錯(cuò)誤。本例中就是加入以下代碼:

protected ? override ? void ?BeforeShellCreated()
{
??
base .BeforeShellCreated();
??RootWorkItem.State[
" dataset " ]? = ? new ?DataSet1();
}

第五步:建立controller

建立controller負(fù)責(zé)用戶信息添加,建立事件源。添加類文件,命名為Form1Controller,將該類從controller繼承。如下代碼所示:

using ?System;
using ?System.Collections.Generic;
using ?System.Text;
using ?Microsoft.Practices.CompositeUI;
using ?Microsoft.Practices.CompositeUI.EventBroker;
using ?Microsoft.Practices.CompositeUI.Utility;
using ?System.Data;
namespace ?TestReport
{
?
public ? class ?Form1Controller:?Controller
?
{
??}


}


在controller中公布一個(gè)事件發(fā)布者,通過(guò)"topic://TestReport/DataRowAdded"來(lái)標(biāo)識(shí)Publisher,默認(rèn)的事件域?yàn)槿帧R部梢酝ㄟ^(guò)PublicationScope枚舉來(lái)設(shè)置事件的作用域。事件作用域有以下三種:

PublicationScope.WorkItem :僅作用于引發(fā)當(dāng)前發(fā)布的WorkItem實(shí)例

PublicationScope.Global:作用于引發(fā)當(dāng)前發(fā)布的WorkItem所有實(shí)例

PublicationScope.Descendants:僅作用于引發(fā)當(dāng)前發(fā)布的WorkItem實(shí)例,以及該WorkItem的任何級(jí)別的子WorkItem實(shí)例。

本例通過(guò)以下代碼發(fā)布事件:

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

controller中主要來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯,于是我們需要添加一個(gè)方法AddNewRow(int sex, string name),用來(lái)實(shí)現(xiàn)人員信息的添加,代碼如下:


private ?DataSet1?ctldataset;
?
// controller的AddNewRow方法,引發(fā)事件DataRowAdded
public ? void ?AddNewRow( int ?sex,? string ?name)
{
if ?(DataRowAdded? != ? null )
{
??DataRow?myRow?
= ?ctldataset.DataTable1.NewRow();
??myRow[
0 ]? = ?sex;
??myRow[
1 ]? = ?name;
??ctldataset.DataTable1.Rows.Add(myRow);
??ctldataset.AcceptChanges();

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

??State.RaiseStateChanged(
" dataset " ,?myRow);
}

}


?? 大家請(qǐng)注意下面代碼,其實(shí)是定義了一個(gè)DictionaryEventArgs參數(shù),并且將當(dāng)前添加的行對(duì)象作為該參數(shù)的值。當(dāng)DataTable1中行添加后,我們引發(fā)事件DataRowAdded(this, args)。? 此時(shí),事件源被觸發(fā)了,訂閱者就可以接收到該事件廣播了。

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

?? 到此,我們已經(jīng)完成了事件源的創(chuàng)建和發(fā)布,為了達(dá)到演示的效果,我們還需要實(shí)現(xiàn)共享WorkItem State來(lái)廣播事件。如以下代碼:


[State( " dataset " )]
public ?DataSet1?CtlDataSet?
{
set ?
{
??ctldataset?
= ?value;
}

}

public ? new ?State?State
{
??
get ? {? return ? base .State;?}
}


??? 我們注意到[State("dataset")]這行代碼,它是用來(lái)表示W(wǎng)orkItem的屬性CtlDataSet,將通過(guò)[State("dataset")]共享出去,同時(shí)當(dāng)CtlDataSet改變時(shí),通過(guò)代碼State.RaiseStateChanged("dataset", myRow),來(lái)引發(fā)狀態(tài)改變事件,其他地方就可以得到該事件的委托。

第六步:整合界面和controller
??? 我們回到Form1.cs編輯代碼。為了讓界面和controller和界面結(jié)合,我們將controller作為界面對(duì)象的一個(gè)屬性,用以下代碼實(shí)現(xiàn):
// 定義該窗體相關(guān)的Controller
private ?Form1Controller?controller;

// 將該窗體相關(guān)的Controller標(biāo)記為自動(dòng)創(chuàng)建實(shí)例
[CreateNew]
public ?Form1Controller?Controller
{
??
set ? {?controller? = ?value;?}
}

?

?? 為添加按鈕加入代碼,實(shí)現(xiàn)添加一個(gè)人員信息:

private ? void ?btn_AddToTable_Click( object ?sender,?EventArgs?e)
{
if (( this .textBox1.Text.Trim().Length? > 0 ))
{
?
this .controller.AddNewRow( this .cmbSex.SelectedIndex,? this .textBox1.Text.Trim());

}

}

?? 還有為了讓Grid和report view能夠同步顯示人員信息,我們需要訂閱由topic://TestReport/DataRowAdded標(biāo)示的事件:

[EventSubscription( " topic://TestReport/DataRowAdded " )]
public ? void ?OnCustomerAdded( object ?sender,?DictionaryEventArgs?e)
{
this .dataGridView1.DataSource? = ?((DataSet1) this .controller.State[ " dataset " ]).DataTable1.DefaultView;
this .DataTable1BindingSource.DataSource? = ?((DataSet1) this .controller.State[ " dataset " ]).DataTable1.DefaultView;
this .reportViewer1.RefreshReport();
}

?? 這樣每添加一個(gè)人員,Grid和Reoport View就能適時(shí)更新自身表現(xiàn)了,這就是Event Broker的實(shí)現(xiàn)方式,簡(jiǎn)單并且簡(jiǎn)潔。前面我們還提到了通過(guò)共享狀態(tài)來(lái)實(shí)現(xiàn)視圖和業(yè)務(wù)對(duì)象的關(guān)聯(lián),在本例中也提供實(shí)現(xiàn)。

首先,在FormLoad事件中訂閱StateChanged事件:

private ? void ?Form1_Load( object ?sender,?EventArgs?e)
{
this .controller.State.StateChanged? += ? new ?EventHandler < StateChangedEventArgs > (State_Changed);
}

然后,通過(guò)代碼更新List狀態(tài):

void ?State_Changed( object ?sender,?StateChangedEventArgs?e)
{
this .listBox1.DataSource? = ?((DataSet1) this .controller.State[ " dataset " ]).DataTable1.DefaultView;
this .listBox1.DisplayMember? = ? " Name " ;
this .listBox1.ValueMember? = ? " Name " ;
}

好了,到此我們的例程已經(jīng)大功告成,最終的運(yùn)行效果如下圖:
Composite UI Application Block學(xué)習(xí)筆記之Event Broker_第2張圖片

本文相關(guān)代碼通過(guò)此連接下載: /Files/hyphappy/TestReport.rar

Composite UI Application Block學(xué)習(xí)筆記之Event Broker


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 新宁县| 十堰市| 抚松县| 绥化市| 石家庄市| 岑溪市| 白水县| 天门市| 武汉市| 镇江市| 安图县| 新宾| 乌兰察布市| 石泉县| 个旧市| 宁南县| 新兴县| 富阳市| 罗平县| 保德县| 双桥区| 红原县| 兰坪| 伊川县| 昆明市| 乌鲁木齐县| 长白| 同仁县| 循化| 江永县| 山西省| 滦南县| 邮箱| 西藏| 九寨沟县| 梁山县| 嵊州市| 巴中市| 平顺县| 大田县| 祁连县|