.net core 常见设计模式-IChangeToken
2021-04-21 16:26
标签:ima 变化 包装 new 完全 情况 llb call 计时 一个对象A,希望它的某些状态在发生改变时通知到B(或C、D), 这种设计有点问题 有个谁说的碰到问题加个中间层就解决了,如果解决不了就再加一层 A和B都引用ChangeToken, 微软定义了一个IChangeToken CancellationChangeToken是一个用的比较多的实现类,它包含一个CancellationToken属性,这个属性是通过构造函数来初始化的(CancellationTokenSource、CancellationToken自行查询相关资料), 因为CancellationToken天然的已经现了IChangeToken,因此CancellationChangeToken只是对CancellationToken的包装。那为啥不直接让CancellationToken实现IChangeToken呢?我感觉是设计意图不同,CancellationToken设计时主要是考虑应用在取消异步操作这件事上的,只是碰巧取消异步操作与更改通知设计思路是相似的,所以才出现CancellationChangeToken 其它的实现类没去研究过,但是只要你对这种设计思路理解了,碰到其它实现类应该看看就明白了 下面我们使用CancellationChangeToken来完成上面的A、B类,A类状态变化时 通知到B类(其实就是执行B类忘ChangeToken中塞入的委托),完整源码如下: 上面只是演示IChangeToken的思路,asp.net core中源码的应用时通常是在A中提供一个返回IChangeToken的方法 上面的方式只能变更通知一次,下面可以永远监控 重点是这句:ChangeToken.OnChange(() => a.CreateChangeToken(), () => Console.WriteLine("a状态变化了")); 这是今天学习的内容,可能理解得不是很准确,仅供参考... .net core 常见设计模式-IChangeToken 标签:ima 变化 包装 new 完全 情况 llb call 计时 原文地址:https://www.cnblogs.com/jionsoft/p/12249326.html场景
常见的做法是在A中定义一个事件(或直接用委托),当状态改变时A去触发这个事件。而B直接订阅这个事件
B由于要订阅A的事件,所以B得完全引用A,其实有时候没必要,因为我只关心A的状态变化而已
状态变更通知这种场景很多,有没有更通用的方式呢?解决思路
B向ChangeToken注册一个委托说:将来你有变化时回调我这个委托
当A的状态变化时会调用ChangeToken的一个方法,这个方法内部就会去触发执行B之前塞进去的委托
此时比如有组件C、D、E..都关心A的状态变化,也可以引用ChangeToken,并向其注册自己的委托
这样ChangeToken可以作为一个通用组件,在很多需要更改通知是场景中使用,如:asp.net core的配置系统、终结点路由、 ....实现
HasChanged:表示当前这个ChangeToken是否变化过了
ActiveChangeCallbacks:当 A触发ChangeToken发生变化时是否主动回调B塞进来的委托
RegisterChangeCallback(Action
简化的源码如下: 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(Actionobject> callback, object state)
15 {
16 return Token.Register(callback, state);
17 }
18 }
例子
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("模拟触发更改通知");
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检测到变化时此委托会被执行
34 //obj是注册委托是传递进来的参数,就是这里的testState
35 Console.WriteLine($"状态变化了,状态值{obj}");
36 }, testState);
37 }
38 }
无限监控与ChangeToken.OnChange
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.OutputEncoding = Encoding.UTF8;
6 var a = new A();
7 //实现无限监控状态变化。OnChange有两个委托类型的参数,我们分别称为委托1和委托2
8 ChangeToken.OnChange(() => a.CreateChangeToken(), () => Console.WriteLine("a状态变化了"));
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("模拟两秒一次触发一次状态修改通知");
24 this._cts.Cancel();
25 }
26 });
27 }
28
29 public IChangeToken CreateChangeToken() {
30 _cts = new CancellationTokenSource();
31 return new CancellationChangeToken(_cts.Token);
32 }
33 }
OnChange有两个委托类型的参数,我们分别称为委托1和委托2,当a的状态变化后会执行委托2,之后会执行委托1,当a状态又变化时又会执行委托2,之后执行委托1,如此往复实现无限监控
文章标题:.net core 常见设计模式-IChangeToken
文章链接:http://soscw.com/index.php/essay/77675.html