Instantly share code, notes, and snippets.

Embed
What would you like to do?
public class DiagnosticsSubstitutionContext : ISubstitutionContext
{
[ThreadStatic]
private static IList<IArgumentSpecification> LastDequeuedList;
private static ConcurrentDictionary<IArgumentSpecification, ArgumentInfo> ArgumentInfos { get; } = new ConcurrentDictionary<IArgumentSpecification, ArgumentInfo>();
private class ArgumentInfo
{
public string CreationStack { get; }
public int DequeueCounter { get; set; }
public int ThreadId { get; }
public DateTime CreationTime { get; }
public ArgumentInfo()
{
CreationStack = Environment.StackTrace;
ThreadId = Thread.CurrentThread.ManagedThreadId;
CreationTime = DateTime.UtcNow;
}
}
static DiagnosticsSubstitutionContext()
{
//Init hook
var context = new DiagnosticsSubstitutionContext(SubstitutionContext.Current);
SubstitutionContext.Current = context;
AppDomain.CurrentDomain.FirstChanceException +=
(sender, args) =>
{
if (args.Exception is AmbiguousArgumentsException)
{
var lastList = LastDequeuedList;
var enqueueInfo = lastList.Select(x => new { Spec = x, Info = ArgumentInfos[x] }).ToArray();
//TODO: PUT breakpoint here or log enqueueInfo.
Thread.CurrentThread.ManagedThreadId
enqueueInfo[x].Spec
enqueueInfo[x].Info.CreationStack
enqueueInfo[x].Info.CreationTime.ToString("o")
enqueueInfo[x].Info.ThreadId
enqueueInfo[x].Info.DequeueCounter
}
};
}
public static void Init() { }
private readonly ISubstitutionContext _original;
private DiagnosticsSubstitutionContext(ISubstitutionContext current)
{
_original = current;
}
public void EnqueueArgumentSpecification(IArgumentSpecification spec)
{
ArgumentInfos.TryAdd(spec, new ArgumentInfo());
_original.EnqueueArgumentSpecification(spec);
}
public IList<IArgumentSpecification> DequeueAllArgumentSpecifications()
{
var result = _original.DequeueAllArgumentSpecifications();
LastDequeuedList = result;
foreach (var argumentSpecification in result)
{
ArgumentInfos[argumentSpecification].DequeueCounter++;
}
return result;
}
//DELEGATING IMPLEMENTATION - NO CHANGES
public ISubstituteFactory SubstituteFactory => _original.SubstituteFactory;
public SequenceNumberGenerator SequenceNumberGenerator => _original.SequenceNumberGenerator;
public ConfiguredCall LastCallShouldReturn(IReturn value, MatchArgs matchArgs) => _original.LastCallShouldReturn(value, matchArgs);
public void LastCallRouter(ICallRouter callRouter) => _original.LastCallRouter(callRouter);
public ICallRouter GetCallRouterFor(object substitute) => _original.GetCallRouterFor(substitute);
public void RaiseEventForNextCall(Func<ICall, object[]> getArguments) => _original.RaiseEventForNextCall(getArguments);
public IQueryResults RunQuery(Action calls) => _original.RunQuery(calls);
public bool IsQuerying => _original.IsQuerying;
public void AddToQuery(object target, ICallSpecification callSpecification) => _original.AddToQuery(target, callSpecification);
public void ClearLastCallRouter() => _original.ClearLastCallRouter();
public IRouteFactory GetRouteFactory() => _original.GetRouteFactory();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment