SchedulerWrapper
using System.Runtime.CompilerServices;
namespace System.Reactive.Concurrency
{
internal abstract class SchedulerWrapper : IScheduler, IServiceProvider
{
protected readonly IScheduler _scheduler;
private readonly ConditionalWeakTable<IScheduler, IScheduler> _cache;
public DateTimeOffset Now => _scheduler.Now;
public SchedulerWrapper(IScheduler scheduler)
{
_scheduler = scheduler;
_cache = new ConditionalWeakTable<IScheduler, IScheduler>();
}
public SchedulerWrapper(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)
{
_scheduler = scheduler;
_cache = cache;
}
public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException("action");
return _scheduler.Schedule(state, Wrap(action));
}
public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException("action");
return _scheduler.Schedule(state, dueTime, Wrap(action));
}
public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException("action");
return _scheduler.Schedule(state, dueTime, Wrap(action));
}
protected virtual Func<IScheduler, TState, IDisposable> Wrap<TState>(Func<IScheduler, TState, IDisposable> action)
{
return (IScheduler self, TState state) => action(GetRecursiveWrapper(self), state);
}
protected IScheduler GetRecursiveWrapper(IScheduler scheduler)
{
return _cache.GetValue(scheduler, (IScheduler s) => Clone(s, _cache));
}
protected abstract SchedulerWrapper Clone(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache);
public object GetService(Type serviceType)
{
IServiceProvider serviceProvider = _scheduler as IServiceProvider;
if (serviceProvider == null)
return null;
if (TryGetService(serviceProvider, serviceType, out object service))
return service;
return serviceProvider.GetService(serviceType);
}
protected abstract bool TryGetService(IServiceProvider provider, Type serviceType, out object service);
}
}