場景

          一個對象A,希望它的某些狀態(tài)在發(fā)生改變時通知到B(或C、D),
          常見的做法是在A中定義一個事件(或直接用委托),當狀態(tài)改變時A去觸發(fā)這個事件。而B直接訂閱這個事件
          ?

          這種設計有點問題
          B由于要訂閱A的事件,所以B得完全引用A,其實有時候沒必要,因為我只關(guān)心A的狀態(tài)變化而已
          狀態(tài)變更通知這種場景很多,有沒有更通用的方式呢?

          ?

          解決思路

          有個誰說的碰到問題加個中間層就解決了,如果解決不了就再加一層


          A和B都引用ChangeToken,
          B向ChangeToken注冊一個委托說:將來你有變化時回調(diào)我這個委托
          當A的狀態(tài)變化時會調(diào)用ChangeToken的一個方法,這個方法內(nèi)部就會去觸發(fā)執(zhí)行B之前塞進去的委托
          此時比如有組件C、D、E..都關(guān)心A的狀態(tài)變化,也可以引用ChangeToken,并向其注冊自己的委托
          這樣ChangeToken可以作為一個通用組件,在很多需要更改通知是場景中使用,如:asp.net core的配置系統(tǒng)、終結(jié)點路由、 ....

          ?

          實現(xiàn)

          微軟定義了一個IChangeToken
          HasChanged:表示當前這個ChangeToken是否變化過了
          ActiveChangeCallbacks:當?A觸發(fā)ChangeToken發(fā)生變化時是否主動回調(diào)B塞進來的委托
          RegisterChangeCallback(Action<object> callback, object
          state):提供一個方法,允許調(diào)用方塞入委托,B就是調(diào)用這個方法向ChangeToken塞入委托的。有一種情況是B希望在塞入委托的同時附帶一個狀態(tài)對象,將來委托被執(zhí)行時這個狀態(tài)對象作為執(zhí)行委托的參數(shù)

          CancellationChangeToken是一個用的比較多的實現(xiàn)類,它包含一個CancellationToken屬性,這個屬性是通過構(gòu)造函數(shù)來初始化的(
          CancellationTokenSource、CancellationToken自行查詢相關(guān)資料),
          簡化的源碼如下:
          1 public class CancellationChangeToken : IChangeToken 2 { 3 public
          CancellationChangeToken(CancellationToken cancellationToken) 4 { 5 Token =
          cancellationToken; 6 } 7 8 public bool ActiveChangeCallbacks { get; private
          set; } = true; 9 10 public bool HasChanged => Token.IsCancellationRequested; 11
          12 private CancellationToken Token { get; } 13 14 public IDisposable
          RegisterChangeCallback(Action<object> callback, object state) 15 { 16 return
          Token.Register(callback, state);17 } 18 }

          因為CancellationToken天然的已經(jīng)現(xiàn)了IChangeToken,因此CancellationChangeToken只是對CancellationToken的包裝。那為啥不直接讓CancellationToken實現(xiàn)IChangeToken呢?我感覺是設計意圖不同,CancellationToken設計時主要是考慮應用在取消異步操作這件事上的,只是碰巧取消異步操作與更改通知設計思路是相似的,所以才出現(xiàn)CancellationChangeToken

          其它的實現(xiàn)類沒去研究過,但是只要你對這種設計思路理解了,碰到其它實現(xiàn)類應該看看就明白了

          例子

          下面我們使用CancellationChangeToken來完成上面的A、B類,A類狀態(tài)變化時
          通知到B類(其實就是執(zhí)行B類忘ChangeToken中塞入的委托),完整源碼如下:
          1 class Program 2 { 3 static void Main(string[] args) 4 { 5
          Console.OutputEncoding = Encoding.UTF8; 6 CancellationTokenSource cts = new
          CancellationTokenSource(); 7 CancellationChangeToken cct = new
          CancellationChangeToken(cts.Token); 8 var a = new A(cts); 9 var b = new B(cct);
          10 Console.ReadKey(); 11 } 12 } 13 14 public class A 15 { 16
          CancellationTokenSource _cts;17 public A(CancellationTokenSource cts) 18 { 19
          this._cts = cts; 20 Task.Run(() => 21 { 22 Task.Delay(2000).Wait(); 23
          Console.WriteLine("模擬觸發(fā)更改通知"); 24 _cts.Cancel(); 25 }); 26 } 27 } 28 public
          class B 29 { 30 public B(CancellationChangeToken cct) { 31 object testState = 1
          ;32 cct.RegisterChangeCallback(obj => { 33 //將來cct檢測到變化時此委托會被執(zhí)行 34 //
          obj是注冊委托是傳遞進來的參數(shù),就是這里的testState 35 Console.WriteLine($"狀態(tài)變化了,狀態(tài)值{obj}"); 36 },
          testState);37 } 38 }
          上面只是演示IChangeToken的思路,asp.net core中源碼的應用時通常是在A中提供一個返回IChangeToken的方法

          無限監(jiān)控與ChangeToken.OnChange

          上面的方式只能變更通知一次,下面可以永遠監(jiān)控
          1 class Program 2 { 3 static void Main(string[] args) 4 { 5
          Console.OutputEncoding = Encoding.UTF8; 6 var a = new A(); 7 //
          實現(xiàn)無限監(jiān)控狀態(tài)變化。OnChange有兩個委托類型的參數(shù),我們分別稱為委托1和委托2 8 ChangeToken.OnChange(() =>
          a.CreateChangeToken(), () => Console.WriteLine("a狀態(tài)變化了")); 9
          Console.ReadKey();10 } 11 } 12 13 public class A 14 { 15
          CancellationTokenSource _cts;16 public A() 17 { 18 Task.Run(() => 19 { 20
          while (true) 21 { 22 Task.Delay(2000).Wait(); 23 Console.WriteLine("
          模擬兩秒一次觸發(fā)一次狀態(tài)修改通知"); 24 this._cts.Cancel(); 25 } 26 }); 27 } 28 29 public
          IChangeToken CreateChangeToken() {30 _cts = new CancellationTokenSource(); 31
          return new CancellationChangeToken(_cts.Token); 32 } 33 }
          重點是這句:ChangeToken.OnChange(() => a.CreateChangeToken(), () =>
          Console.WriteLine("a狀態(tài)變化了"));

          OnChange有兩個委托類型的參數(shù),我們分別稱為委托1和委托2,當a的狀態(tài)變化后會執(zhí)行委托2,之后會執(zhí)行委托1,當a狀態(tài)又變化時又會執(zhí)行委托2,之后執(zhí)行委托1,如此往復實現(xiàn)無限監(jiān)控?

          這是今天學習的內(nèi)容,可能理解得不是很準確,僅供參考...

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                一级黄色免费在线观看 | 国产免费A级成人片在线观看 | 四色成人 | 中国黄大片 | aaa的视频 |