ChangeToken是个
静态类:public static class ChangeToken { public static IDisposable OnChange(Func<IChangeToken> changeTokenProducer, Action changeTokenConsumer); }
该类仅仅提供了一个OnChange
的静态方法,而该方法需要一个返回类型为IChangeToken
的参数。而一看这个命名**Token
,是不是很像CancellationToken
,拥有了它,就会得到通知。 这种东西官方的名称其实叫做“令牌”。所以,您可能都会猜到,它可能会具有一个注册回调的方法:
public interface IChangeToken { bool HasChanged { get; } bool ActiveChangeCallbacks { get; } IDisposable RegisterChangeCallback(Action<object> callback, object state); }
那么,它存在的意义是什么呢? 高层的抽象!
比如下方的代码:
Console.WriteLine("开始监测文件夹 c:\\temp"); var phyFileProvider = new PhysicalFileProvider("c:\\temp"); IChangeToken changeToken = phyFileProvider.Watch("*.*"); changeToken.RegisterChangeCallback(_ => { Console.WriteLine("检测到文件夹有变化!" + _); }, "xiaoming");
像不像一个叫做PhysicalFileProvider
的运营商,给我发了一个令牌。当我拥有这个令牌之后,运营商就可以联系到我了,当它联系我的时候,我就可以做出对应的反应。比如上面是打印一排字出来。
而在“物理文件”这个圈子里面,IChangeToken
的真身叫做PollingFileChangeToken
;
在“配置系统”这个圈子里面,IChangeToken
的真身叫做ConfigurationReloadToken
。
如果咱们想实现自己的IChangeToken
怎么办呢?还记得最上面的CancellationTokenSource
吗?既然.Net为咱们提供了一个线程安全而又直接可以拿来用的工具:
public class MyOwnChangeToken : IChangeToken { public CancellationTokenSource _cts = new CancellationTokenSource(); public bool ActiveChangeCallbacks => true; public bool HasChanged => _cts.IsCancellationRequested; public IDisposable RegisterChangeCallback(Action<object> callback, object state) => _cts.Token.Register(callback, state); public void MyOwnChange() => _cts.Cancel(); }
在“我自己的这个圈子”,就可以使用MyOwnChangeToken
了,当外界获取到我的IChangeToken
,我就可以触发MyOwnChange
来通知他们了。
其实.NET Core中大部分的IChangeToken
内部都使用了CancellationTokenSource
。
搞懂了IChangeToken
我们就很轻松就能理解了ChangeToken
,作为静态类的它,肯定是作为一个工具类的实现。
ChangeToken.OnChange( () => physicalFileProvider.Watch("*.*"), () => Console.WriteLine("检测到文件夹有变化!") );
那么您可能会说,我直接使用pysicalFileProvider.Watch()方法返回的IChangeToken的RegisterChangeCallback
方法订阅不行吗?他们有什么区别吗? 答案是:“调用次数”。使用RegisterChangeCallback
的方法,只会执行一次回调内容,因为当“令牌”用了一次之后,其实它就失效了。所以上面那个监控文件改动的代码,当第二次文件改动的时候,它其实是不会再执行回调的。
而使用ChangeToken
这个静态类,它就可以帮助您不断的去获取新“令牌”然后注册对应的回调,所以就能够保证咱们多次改变也能触发回调了。
所以来看上面的这一段代码 ChangeToken.OnChange(() => physicalFileProvider.Watch("*.*"),...)
,“phyFileProvider
”这个“供应商”可以为我们提供“令牌”,当该令牌发生改动的时候,我们就有机会去完成操作了。
() => physicalFileProvider.Watch("*.*")
这部分代码我们可以称它为“令牌生产过程”,而() => Console.WriteLine("检测到文件夹有变化!")
叫做“令牌的消费过程”。
ChangeToken
干的事情就是:当消费者消费之后,就又会去让“生产过程”再生成一个令牌出来,并且在该令牌上挂载“消费过程”,这样就能保证能够一直“观察”下去了。
案例1:添加缓存时提供IChangeToken,当依赖文件修改时,删除缓存
var fileProvider = new PhysicalFileProvider(Path.GetDirectoryName(dependencyFile)); var changeToken = fileProvider.Watch(Path.GetFileName(dependencyFile)); cache.Set(key, value, new MemoryCacheEntryOptions().AddExpirationToken(changeToken);
案例2:配置文件统一读取类,当配置文件修改时,利用ChangeToken重新读取配置
public class ConfigSetting { private IConfiguration _configuration = null; public ConfigSetting(IConfiguration configuration) { _configuration = configuration; ChangeToken.OnChange(()=>configuration.GetReloadToken(), () => { reloadConfiguration(); }); reloadConfiguration(); } private void reloadConfiguration() { _siteName = _configuration["SiteName"]; _siteID = _configuration.GetValue<int>("SiteID"); } private string _siteName = null; private int _siteID = 0; public string SiteName { get{return _siteName; } } public int SiteID { get{return _siteID; } } }
参考:https://www.cnblogs.com/uoyo/p/12509871.html
.Net Core中的令牌ChangeToken、IChangeToken介绍
原文:https://www.cnblogs.com/fanfan-90/p/12772732.html