public static EventInfo ParseAddHandlerAction(this MocksRepository repo, Action addHandlerAction, out object instance) { EventInfo theEvent = null; object instanceVar = null; var recorder = new DelegatingRecorder(); recorder.Record += invocation => { var candidateEvent = invocation.Method.GetEventFromAddOrRemove(); if (candidateEvent != null) { theEvent = candidateEvent; instanceVar = MocksRepository.GetMockMixin(invocation.Instance, theEvent.DeclaringType) ?? invocation.Instance; } }; using (repo.StartRecording(recorder, true)) { addHandlerAction(); } instance = instanceVar; return(theEvent); }
internal static CallPattern FromAction(MocksRepository repository, Action memberAction, bool dispatchToMethodMocks = false) { var callPattern = new CallPattern(); Invocation lastInvocation = null; var recorder = new DelegatingRecorder(); recorder.Record += invocation => lastInvocation = invocation; using (repository.StartRecording(recorder, dispatchToMethodMocks)) { memberAction(); } if (lastInvocation == null) { throw new MockException("The specified action did not call a mocked method."); } callPattern.SetMethod(lastInvocation.Method, checkCompatibility: true); callPattern.InstanceMatcher = new ReferenceMatcher(lastInvocation.Instance); // Because it's impossible to distinguish between a literal value passed as an argument and // one coming from a matcher, it is impossible to tell exactly which arguments are literal and which are matchers. // So, we assume that the user always first specifies some literal values, and then some matchers. // We assume that the user will never pass a literal after a matcher. using (repository.StartArrangeArgMatching()) { for (int i = 0; i < lastInvocation.Args.Length; ++i) { var indexInMatchers = i - (lastInvocation.Args.Length - repository.MatchersInContext.Count); var matcher = indexInMatchers >= 0 ? repository.MatchersInContext[indexInMatchers] : new ValueMatcher(lastInvocation.Args[i]); callPattern.ArgumentMatchers.Add(matcher); } } repository.MatchersInContext.Clear(); callPattern.AdjustForExtensionMethod(); return(callPattern); }