封裝stream,在讀寫stream時提供事件通知_.Net教程
推薦:實例開發:ASP.NET創建網絡相冊在現在的數碼時代,我們會經常拍攝一些相片以供留念,而隨著數碼照片的增多,往往需要很好地管理這些照片,以便更好地查閱留念。現在網上有不少的電子相冊,都能很好的實現這些功能,那我們能否
前陣子的工作涉及一些網絡編程,使用了面向流的方式做傳輸數據。在代碼過程中,遇到一個新需求就是要統計流量。其實最簡單的辦法就時在讀寫流的地方增加代碼,把功能增加上去就可以。但是我覺得那樣對我原理的代碼框架影響較大,基于盡量不影響原來的代碼的考慮,我想到了Decorator設計模式。
先把代碼貼出來,在做解釋吧:
| 以下為引用的內容: 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> |
剛開始以為很簡單,事實上寫下來還挺多行代碼的,Decorator模式嘛,當然先繼承stream,把stream本來該做的事情先完成了。這個很簡單類里面包含一個內部的stream,stream該有的接口都由它來完成了。接下來就是增加兩個事件,分別是OnBeforeRead、OnBeforeWrite。名字里面都有Before,其實我考慮到數據流都會通過這兩個事件開放出來,你想做加密什么的都可以,當然也包括我想要的統計數據流量。
接下來就是在讀寫流的時候觸發這兩個事件就可以了。看看同步的Read、Write方法,簡單的調用就可以了。
關鍵的地方就在于異步的讀寫。
我們先看看一般Stream的異步調用代碼是怎么樣的:
| 以下為引用的內容: stream.BeginRead(buffer, 0, byte2read, new AsyncCallback(EndReadCallback), state); private void EndReadCallback(IAsyncResult asyncResult) |
在不更改這個“client”代碼的情況下,要怎么樣在stream那邊知道這里的確實讀了多少數據呢?
顯然在調用BeginRead的時候是不知道,那就只能對這個AsyncCallback做手腳了。可以預想到framework內部會在完成了Read的操作之后會調用AsyncCallback委托來通知結果。于是我就傳一個我定義好的AsyncCallback委托給BeginRead。當然還要把“client”提供的AsyncCallback給包裝起來,在做完我的事情(事件通知)之后,還是要把“client”要我辦的事情給也給辦了(調用"client"的AsyncCallback委托來通知結果)。
這就在實現了“在客戶代碼與framework之間插一腳”。
再來看看我是怎么做到事件通知的。首先要把我要的數據給傳過去,于是有了InternalAsyncState,這里面要有我觸發事件需要的事件參數,還應該要包括用戶可能傳入的state。具體大家看看InternalAsyncState的實現。
最后多考慮了一點就是,假如“client”代碼不是像我寫的那樣,而是不斷的通過檢查Stream.BeginRead 方法返回的IAsyncResult的IsCompleted屬性來確定是否Read完成的話,那我的代碼就有問題了,我返回的IAsyncResult根本就不是原理的IAsyncResult了。EventStreamAsyncResult類就是為這個而寫的。
下面是使用的代碼:
| 以下為引用的內容: 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; } |
回頭看看代碼,其實都在用Decorator模式的思想,把原來的framework中的類都給包裝起來,并在完成原來的功能之余另外加了自己的功能。
文筆一般,希望能對你有幫助。
分享:“黑盒測試管理”以外的編程經驗片斷除了很好地進行“黑盒測試管理”,個人覺得下述更值得用功;畢竟“前除后略”! 1、架構和算法的可行性測試分析:主要包括性能、并發等方面 2、CodeReview:很簡單,但
- asp.net如何得到GRIDVIEW中某行某列值的方法
- .net SMTP發送Email實例(可帶附件)
- js實現廣告漂浮效果的小例子
- asp.net Repeater 數據綁定的具體實現
- Asp.Net 無刷新文件上傳并顯示進度條的實現方法及思路
- Asp.net獲取客戶端IP常見代碼存在的偽造IP問題探討
- VS2010 水晶報表的使用方法
- ASP.NET中操作SQL數據庫(連接字符串的配置及獲取)
- asp.net頁面傳值測試實例代碼
- DataGridView - DataGridViewCheckBoxCell的使用介紹
- asp.net中javascript的引用(直接引入和間接引入)
- 三層+存儲過程實現分頁示例代碼
- 相關鏈接:
- 教程說明:
.Net教程-封裝stream,在讀寫stream時提供事件通知
。