/
CallRouter.cs
125 lines (103 loc) · 4.51 KB
/
CallRouter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
using System;
using System.Collections.Generic;
using System.Linq;
using NSubstitute.Core.Arguments;
using NSubstitute.Exceptions;
using NSubstitute.Routing;
namespace NSubstitute.Core
{
public class CallRouter : ICallRouter
{
private readonly ISubstituteState _substituteState;
private readonly IThreadLocalContext _threadContext;
private readonly IRouteFactory _routeFactory;
private readonly bool _canConfigureBaseCalls;
public CallRouter(ISubstituteState substituteState, IThreadLocalContext threadContext, IRouteFactory routeFactory, bool canConfigureBaseCalls)
{
_substituteState = substituteState;
_threadContext = threadContext;
_routeFactory = routeFactory;
_canConfigureBaseCalls = canConfigureBaseCalls;
}
public bool CallBaseByDefault
{
get => _substituteState.CallBaseConfiguration.CallBaseByDefault;
set
{
if (!_canConfigureBaseCalls) throw CouldNotConfigureCallBaseException.ForAllCalls();
_substituteState.CallBaseConfiguration.CallBaseByDefault = value;
}
}
public void Clear(ClearOptions options)
{
if ((options & ClearOptions.CallActions) == ClearOptions.CallActions)
{
_substituteState.CallActions.Clear();
}
if ((options & ClearOptions.ReturnValues) == ClearOptions.ReturnValues)
{
_substituteState.CallResults.Clear();
_substituteState.ResultsForType.Clear();
}
if ((options & ClearOptions.ReceivedCalls) == ClearOptions.ReceivedCalls)
{
_substituteState.ReceivedCalls.Clear();
}
}
public IEnumerable<ICall> ReceivedCalls()
{
return _substituteState.ReceivedCalls.AllCalls();
}
public void SetRoute(Func<ISubstituteState, IRoute> getRoute) =>
_threadContext.SetNextRoute(this, getRoute);
public object Route(ICall call)
{
_threadContext.SetLastCallRouter(this);
var isQuerying = _threadContext.IsQuerying;
var pendingRaisingEventArgs = _threadContext.UsePendingRaisingEventArgumentsFactory();
var queuedNextRouteFactory = _threadContext.UseNextRoute(this);
IRoute routeToUse = ResolveCurrentRoute(call, isQuerying, pendingRaisingEventArgs, queuedNextRouteFactory);
return routeToUse.Handle(call);
}
private IRoute ResolveCurrentRoute(ICall call, bool isQuerying, Func<ICall, object[]> pendingRaisingEventArgs, Func<ISubstituteState, IRoute> queuedNextRouteFactory)
{
if (isQuerying)
{
return _routeFactory.CallQuery(_substituteState);
}
if (pendingRaisingEventArgs != null)
{
return _routeFactory.RaiseEvent(_substituteState, pendingRaisingEventArgs);
}
if (queuedNextRouteFactory != null)
{
return queuedNextRouteFactory.Invoke(_substituteState);
}
if (IsSpecifyingACall(call))
{
return _routeFactory.RecordCallSpecification(_substituteState);
}
return _routeFactory.RecordReplay(_substituteState);
}
private static bool IsSpecifyingACall(ICall call)
{
return call.GetOriginalArguments().Length != 0 && call.GetArgumentSpecifications().Count != 0;
}
public ConfiguredCall LastCallShouldReturn(IReturn returnValue, MatchArgs matchArgs, PendingSpecificationInfo pendingSpecInfo)
{
if (returnValue == null) throw new ArgumentNullException(nameof(returnValue));
if (matchArgs == null) throw new ArgumentNullException(nameof(matchArgs));
if (pendingSpecInfo == null) throw new ArgumentNullException(nameof(pendingSpecInfo));
return _substituteState.ConfigureCall.SetResultForLastCall(returnValue, matchArgs, pendingSpecInfo);
}
public void SetReturnForType(Type type, IReturn returnValue)
{
_substituteState.ResultsForType.SetResult(type, returnValue);
}
public void RegisterCustomCallHandlerFactory(CallHandlerFactory factory)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
_substituteState.CustomHandlers.AddCustomHandlerFactory(factory);
}
}
}