Created
October 3, 2018 03:18
-
-
Save Shaddix/30d7c6b7d6b3ad445ae62529fa56b387 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
namespace WebAppTests.DateTimeSpike | |
{ | |
public class DateTimeProvider | |
{ | |
private static readonly Lazy<DateTimeProvider> _lazyInstance = new Lazy<DateTimeProvider>(() => new DateTimeProvider()); | |
public static DateTimeProvider Instance => _lazyInstance.Value; | |
private readonly Func<DateTimeOffset> _defaultDateTimeFunction = () => DateTimeOffset.Now; | |
private DateTimeProvider() | |
{ | |
} | |
/// <summary> | |
/// DateTimeProvider.Instance.Now will return passed dateTime until return DateTimeProviderContext is disposed. | |
/// Use wrapped in using like: | |
/// using (var dateTimeContext = DateTimeProvider.Instance.SimulateTime(/*new DateTimeOffset()*/)) | |
/// { | |
/// //DateTimeProvider.Instance.Now will return configured DateTime | |
/// } | |
/// </summary> | |
/// <param name="dateTime"></param> | |
/// <returns></returns> | |
internal DateTimeProviderContext SimulateTime(DateTimeOffset dateTime) | |
{ | |
return new DateTimeProviderContext(dateTime); | |
} | |
public DateTimeOffset Now | |
{ | |
get | |
{ | |
if (DateTimeProviderContext.Current == null) | |
{ | |
return _defaultDateTimeFunction.Invoke(); | |
} | |
else | |
{ | |
return DateTimeProviderContext.Current.ContextDateTimeNow; | |
} | |
} | |
} | |
} | |
internal class DateTimeProviderContext : IDisposable | |
{ | |
private static readonly AsyncLocal<Stack<DateTimeProviderContext>> ScopeStack = new AsyncLocal<Stack<DateTimeProviderContext>>() | |
{ | |
Value = new Stack<DateTimeProviderContext>() | |
}; | |
public DateTimeOffset ContextDateTimeNow { get; set; } | |
public DateTimeProviderContext(DateTimeOffset contextDateTimeNow) | |
{ | |
ContextDateTimeNow = contextDateTimeNow; | |
ScopeStack.Value.Push(this); | |
} | |
public static DateTimeProviderContext Current | |
{ | |
get | |
{ | |
if (ScopeStack.Value.Count == 0) | |
{ | |
return null; | |
} | |
return ScopeStack.Value.Peek(); | |
} | |
} | |
public static void Reset() | |
{ | |
ScopeStack.Value.Clear(); | |
} | |
public void Dispose() | |
{ | |
try | |
{ | |
ScopeStack.Value.Pop(); | |
} | |
catch (Exception e) | |
{ | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment