<PackageReference Include="Microsoft.Extensions.Primitives" Version="10.0.0-rc.1.25451.107" />

ChangeToken

public static class ChangeToken
Propagates notifications that a change has occurred.
using System; using System.Runtime.CompilerServices; using System.Threading; namespace Microsoft.Extensions.Primitives { [NullableContext(1)] [Nullable(0)] public static class ChangeToken { private sealed class ChangeTokenRegistration<TState> : IDisposable { private sealed class NoopDisposable : IDisposable { public void Dispose() { } } private readonly Func<IChangeToken> _changeTokenProducer; private readonly Action<TState> _changeTokenConsumer; private readonly TState _state; private IDisposable _disposable; private static readonly NoopDisposable _disposedSentinel = new NoopDisposable(); public ChangeTokenRegistration(Func<IChangeToken> changeTokenProducer, Action<TState> changeTokenConsumer, TState state) { _changeTokenProducer = changeTokenProducer; _changeTokenConsumer = changeTokenConsumer; _state = state; IChangeToken token = changeTokenProducer(); RegisterChangeTokenCallback(token); } private void OnChangeTokenFired() { IChangeToken token = _changeTokenProducer(); try { _changeTokenConsumer(_state); } finally { RegisterChangeTokenCallback(token); } } private void RegisterChangeTokenCallback(IChangeToken token) { if (token != null) { IDisposable disposable = token.RegisterChangeCallback(delegate(object s) { ((ChangeTokenRegistration<TState>)s).OnChangeTokenFired(); }, this); if (token.HasChanged && token.ActiveChangeCallbacks) disposable?.Dispose(); else SetDisposable(disposable); } } private void SetDisposable(IDisposable disposable) { IDisposable disposable2 = Volatile.Read<IDisposable>(ref _disposable); if (disposable2 == _disposedSentinel) disposable.Dispose(); else { IDisposable disposable3 = Interlocked.CompareExchange<IDisposable>(ref _disposable, disposable, disposable2); if (disposable3 == _disposedSentinel) disposable.Dispose(); else if (disposable3 != disposable2) { throw new InvalidOperationException("Somebody else set the _disposable field"); } } } public void Dispose() { Interlocked.Exchange<IDisposable>(ref _disposable, (IDisposable)_disposedSentinel)?.Dispose(); } } public static IDisposable OnChange([Nullable(new byte[] { 1, 2 })] Func<IChangeToken> changeTokenProducer, Action changeTokenConsumer) { if (changeTokenProducer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.changeTokenProducer); if (changeTokenConsumer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.changeTokenConsumer); return new ChangeTokenRegistration<Action>(changeTokenProducer, delegate(Action callback) { callback(); }, changeTokenConsumer); } public static IDisposable OnChange<[Nullable(2)] TState>([Nullable(new byte[] { 1, 2 })] Func<IChangeToken> changeTokenProducer, Action<TState> changeTokenConsumer, TState state) { if (changeTokenProducer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.changeTokenProducer); if (changeTokenConsumer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.changeTokenConsumer); return new ChangeTokenRegistration<TState>(changeTokenProducer, changeTokenConsumer, state); } } }