<PackageReference Include="Microsoft.Extensions.Primitives" Version="10.0.0-preview.3.25171.5" />

CompositeChangeToken

An IChangeToken that represents one or more IChangeToken instances.
using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Threading; namespace Microsoft.Extensions.Primitives { [NullableContext(1)] [Nullable(0)] [DebuggerDisplay("HasChanged = {HasChanged}")] public class CompositeChangeToken : IChangeToken { private static readonly Action<object> _onChangeDelegate = OnChange; private readonly object _callbackLock = new object(); private CancellationTokenSource _cancellationTokenSource; private List<IDisposable> _disposables; [MemberNotNullWhen(true, "_cancellationTokenSource")] [MemberNotNullWhen(true, "_disposables")] private bool RegisteredCallbackProxy { [MemberNotNullWhen(true, "_cancellationTokenSource")] [MemberNotNullWhen(true, "_disposables")] get; [MemberNotNullWhen(true, "_cancellationTokenSource")] [MemberNotNullWhen(true, "_disposables")] set; } public IReadOnlyList<IChangeToken> ChangeTokens { get; } public bool HasChanged { get { if (_cancellationTokenSource != null && _cancellationTokenSource.Token.IsCancellationRequested) return true; for (int i = 0; i < ChangeTokens.Count; i++) { if (ChangeTokens[i].HasChanged) { OnChange(this); return true; } } return false; } } public bool ActiveChangeCallbacks { get; } public CompositeChangeToken(IReadOnlyList<IChangeToken> changeTokens) { if (changeTokens == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.changeTokens); ChangeTokens = changeTokens; int num = 0; while (true) { if (num >= ChangeTokens.Count) return; if (ChangeTokens[num].ActiveChangeCallbacks) break; num++; } ActiveChangeCallbacks = true; } public IDisposable RegisterChangeCallback([Nullable(new byte[] { 1, 2 })] Action<object> callback, [Nullable(2)] object state) { EnsureCallbacksInitialized(); return _cancellationTokenSource.Token.Register(callback, state); } [MemberNotNull("_cancellationTokenSource")] [MemberNotNull("_disposables")] private void EnsureCallbacksInitialized() { if (!RegisteredCallbackProxy) { lock (_callbackLock) { if (!RegisteredCallbackProxy) { _cancellationTokenSource = new CancellationTokenSource(); _disposables = new List<IDisposable>(); for (int i = 0; i < ChangeTokens.Count; i++) { if (ChangeTokens[i].ActiveChangeCallbacks) { IDisposable disposable = ChangeTokens[i].RegisterChangeCallback(_onChangeDelegate, this); if (_cancellationTokenSource.IsCancellationRequested) { disposable.Dispose(); break; } _disposables.Add(disposable); } } RegisteredCallbackProxy = true; } } } } private static void OnChange(object state) { CompositeChangeToken compositeChangeToken = (CompositeChangeToken)state; if (compositeChangeToken._cancellationTokenSource != null) { lock (compositeChangeToken._callbackLock) { if (compositeChangeToken._cancellationTokenSource.IsCancellationRequested) return; try { compositeChangeToken._cancellationTokenSource.Cancel(); } catch { } } List<IDisposable> disposables = compositeChangeToken._disposables; for (int i = 0; i < disposables.Count; i++) { disposables[i].Dispose(); } } } } }