封裝stream,在讀寫stream時(shí)提供事件通知_.Net教程
推薦:實(shí)例開發(fā):ASP.NET創(chuàng)建網(wǎng)絡(luò)相冊在現(xiàn)在的數(shù)碼時(shí)代,我們會(huì)經(jīng)常拍攝一些相片以供留念,而隨著數(shù)碼照片的增多,往往需要很好地管理這些照片,以便更好地查閱留念�,F(xiàn)在網(wǎng)上有不少的電子相冊,都能很好的實(shí)現(xiàn)這些功能,那我們能否
前陣子的工作涉及一些網(wǎng)絡(luò)編程,使用了面向流的方式做傳輸數(shù)據(jù)。在代碼過程中,遇到一個(gè)新需求就是要統(tǒng)計(jì)流量。其實(shí)最簡單的辦法就時(shí)在讀寫流的地方增加代碼,把功能增加上去就可以。但是我覺得那樣對我原理的代碼框架影響較大,基于盡量不影響原來的代碼的考慮,我想到了Decorator設(shè)計(jì)模式。
先把代碼貼出來,在做解釋吧:
| 以下為引用的內(nèi)容: public class EventStream : Stream { public event EventHandler<FStreamDataEventArgs> OnBeforeRead; public event EventHandler<FStreamDataEventArgs> OnBeforeWrite; private Stream stream; [ ==== Stream members ==== ]#region [ ==== Stream members ==== ] public override bool CanSeek public override bool CanWrite public override void Flush() public override long Length public override long Position public override int Read(byte[] buffer, int offset, int count) public override long Seek(long offset, SeekOrigin origin) public override void SetLength(long value) public override void Write(byte[] buffer, int offset, int count) public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, public override int EndRead(IAsyncResult asyncResult) public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) public override void EndWrite(IAsyncResult asyncResult) #endregion private class InternalCallback public InternalCallback(EventHandler<FStreamDataEventArgs> internalHandler, AsyncCallback callback) internal void Callback(IAsyncResult asyncResult) private class InternalAsyncState public object State public FStreamDataEventArgs StreamDataEventArgs public InternalAsyncState(FStreamDataEventArgs streamDataEventArgs, object state) private class EventStreamAsyncResult : IAsyncResult public EventStreamAsyncResult(IAsyncResult ar) public object AsyncState internal IAsyncResult InternalAsyncResult public System.Threading.WaitHandle AsyncWaitHandle public bool CompletedSynchronously public bool IsCompleted #endregion public class FStreamDataEventArgs : EventArgs public FStreamDataEventArgs(byte[] buffer, int offset, int count) this.buffer = buffer; /**//// <summary> /**//// <summary> /**//// <summary> |
剛開始以為很簡單,事實(shí)上寫下來還挺多行代碼的,Decorator模式嘛,當(dāng)然先繼承stream,把stream本來該做的事情先完成了。這個(gè)很簡單類里面包含一個(gè)內(nèi)部的stream,stream該有的接口都由它來完成了。接下來就是增加兩個(gè)事件,分別是OnBeforeRead、OnBeforeWrite。名字里面都有Before,其實(shí)我考慮到數(shù)據(jù)流都會(huì)通過這兩個(gè)事件開放出來,你想做加密什么的都可以,當(dāng)然也包括我想要的統(tǒng)計(jì)數(shù)據(jù)流量。
接下來就是在讀寫流的時(shí)候觸發(fā)這兩個(gè)事件就可以了�?纯赐降腞ead、Write方法,簡單的調(diào)用就可以了。
關(guān)鍵的地方就在于異步的讀寫。
我們先看看一般Stream的異步調(diào)用代碼是怎么樣的:
| 以下為引用的內(nèi)容: stream.BeginRead(buffer, 0, byte2read, new AsyncCallback(EndReadCallback), state); private void EndReadCallback(IAsyncResult asyncResult) |
在不更改這個(gè)“client”代碼的情況下,要怎么樣在stream那邊知道這里的確實(shí)讀了多少數(shù)據(jù)呢?
顯然在調(diào)用BeginRead的時(shí)候是不知道,那就只能對這個(gè)AsyncCallback做手腳了。可以預(yù)想到framework內(nèi)部會(huì)在完成了Read的操作之后會(huì)調(diào)用AsyncCallback委托來通知結(jié)果。于是我就傳一個(gè)我定義好的AsyncCallback委托給BeginRead。當(dāng)然還要把“client”提供的AsyncCallback給包裝起來,在做完我的事情(事件通知)之后,還是要把“client”要我辦的事情給也給辦了(調(diào)用"client"的AsyncCallback委托來通知結(jié)果)。
這就在實(shí)現(xiàn)了“在客戶代碼與framework之間插一腳”。
再來看看我是怎么做到事件通知的。首先要把我要的數(shù)據(jù)給傳過去,于是有了InternalAsyncState,這里面要有我觸發(fā)事件需要的事件參數(shù),還應(yīng)該要包括用戶可能傳入的state。具體大家看看InternalAsyncState的實(shí)現(xiàn)。
最后多考慮了一點(diǎn)就是,假如“client”代碼不是像我寫的那樣,而是不斷的通過檢查Stream.BeginRead 方法返回的IAsyncResult的IsCompleted屬性來確定是否Read完成的話,那我的代碼就有問題了,我返回的IAsyncResult根本就不是原理的IAsyncResult了。EventStreamAsyncResult類就是為這個(gè)而寫的。
下面是使用的代碼:
| 以下為引用的內(nèi)容: public void GetResponseStream() { EventStream es = new EventStream(tcpClient.NetStream); es.OnBeforeRead = new EventHandler<FStreamDataEventArgs>(EventStream_OnBeforeRead); es.OnBeforeWrite = new EventHandler<FStreamDataEventArgs>(EventStream_OnBeforeWrite); return es; } |
回頭看看代碼,其實(shí)都在用Decorator模式的思想,把原來的framework中的類都給包裝起來,并在完成原來的功能之余另外加了自己的功能。
文筆一般,希望能對你有幫助。
分享:“黑盒測試管理”以外的編程經(jīng)驗(yàn)片斷除了很好地進(jìn)行“黑盒測試管理”,個(gè)人覺得下述更值得用功;畢竟“前除后略”! 1、架構(gòu)和算法的可行性測試分析:主要包括性能、并發(fā)等方面 2、CodeReview:很簡單,但
- asp.net如何得到GRIDVIEW中某行某列值的方法
- .net SMTP發(fā)送Email實(shí)例(可帶附件)
- js實(shí)現(xiàn)廣告漂浮效果的小例子
- asp.net Repeater 數(shù)據(jù)綁定的具體實(shí)現(xiàn)
- Asp.Net 無刷新文件上傳并顯示進(jìn)度條的實(shí)現(xiàn)方法及思路
- Asp.net獲取客戶端IP常見代碼存在的偽造IP問題探討
- VS2010 水晶報(bào)表的使用方法
- ASP.NET中操作SQL數(shù)據(jù)庫(連接字符串的配置及獲取)
- asp.net頁面?zhèn)髦禍y試實(shí)例代碼
- DataGridView - DataGridViewCheckBoxCell的使用介紹
- asp.net中javascript的引用(直接引入和間接引入)
- 三層+存儲(chǔ)過程實(shí)現(xiàn)分頁示例代碼
.Net教程Rss訂閱編程教程搜索
.Net教程推薦
- Repeater綁定dictionary數(shù)據(jù)源代碼及報(bào)錯(cuò)解決
- 在ASP.NET中跨頁面實(shí)現(xiàn)多選
- 揭秘設(shè)計(jì)ASP.NET應(yīng)用程序的七大妙招
- XML文件修改節(jié)點(diǎn)屬性值(多種方法)
- 怎樣在VC中實(shí)現(xiàn)淡入淡出的啟動(dòng)畫面
- 使用ADO.NET2.0提升數(shù)據(jù)交互性能(4)
- 淺析CMS內(nèi)容管理系統(tǒng)的兩種方案
- 使用Data Access Application Block 得到存儲(chǔ)過程的返回值
- c#多圖片上傳并生成縮略圖的實(shí)例代碼
- ASP.NET常用的三十三種實(shí)用代碼
- 相關(guān)鏈接:
- 教程說明:
.Net教程-封裝stream,在讀寫stream時(shí)提供事件通知
。