Esempio n. 1
0
        public static EventWithTarget GetEventWithTarget <TMock>(this Action <TMock> eventExpression, TMock mock)
            where TMock : class
        {
            Guard.NotNull(eventExpression, nameof(eventExpression));

            MethodBase addRemove;
            Mock       target;

            using (var observer = AmbientObserver.Activate())
            {
                eventExpression(mock);

                if (!observer.LastIsInvocation(out target, out var invocation, out _))
                {
                    throw new ArgumentException(Resources.ExpressionIsNotEventAttachOrDetachOrIsNotVirtual);
                }

                addRemove = invocation.Method;
            }

            var ev = addRemove.DeclaringType.GetEvent(
                addRemove.Name.Replace("add_", string.Empty).Replace("remove_", string.Empty));

            if (ev == null)
            {
                throw new ArgumentException(string.Format(
                                                CultureInfo.CurrentCulture,
                                                Resources.EventNotFound,
                                                addRemove));
            }

            return(new EventWithTarget(ev, target));
        }
 public static bool IsMatch(this Expression expression, out Match match)
 {
     using (var observer = AmbientObserver.Activate())
     {
         Expression.Lambda <Action>(expression).CompileUsingExpressionCompiler().Invoke();
         return(observer.LastIsMatch(out match));
     }
 }
Esempio n. 3
0
        private static SetupSetImplResult SetupSetImpl(Mock mock, Delegate setterExpression)
        {
            Mock       target;
            Invocation invocation;

            AmbientObserver.Matches matches;

            using (var observer = AmbientObserver.Activate())
            {
                setterExpression.DynamicInvoke(mock.Object);

                if (!observer.LastIsInvocation(out target, out invocation, out matches))
                {
                    throw new ArgumentException(string.Format(
                                                    CultureInfo.InvariantCulture,
                                                    Resources.SetupOnNonVirtualMember,
                                                    string.Empty));
                }
            }

            var setter = invocation.Method;

            if (!setter.IsPropertySetter())
            {
                throw new ArgumentException(Resources.SetupNotSetter);
            }

            // No need to call ThrowIfCantOverride as non-overridable would have thrown above already.

            // Get the variable name as used in the actual delegate :)
            // because of delegate currying, look at the last parameter for the Action's backing method, not the first
            var setterExpressionParameters = setterExpression.GetMethodInfo().GetParameters();
            var parameterName = setterExpressionParameters[setterExpressionParameters.Length - 1].Name;
            var x             = Expression.Parameter(invocation.Method.DeclaringType, parameterName);

            var arguments  = invocation.Arguments;
            var parameters = setter.GetParameters();
            var values     = new Expression[arguments.Length];

            if (matches.Count == 0)
            {
                // Length == 1 || Length == 2 (Indexer property)
                for (int i = 0; i < arguments.Length; i++)
                {
                    values[i] = GetValueExpression(arguments[i], parameters[i].ParameterType);
                }

                var lambda = Expression.Lambda(
                    typeof(Action <>).MakeGenericType(x.Type),
                    Expression.Call(x, invocation.Method, values),
                    x);

                return(new SetupSetImplResult(target, lambda, invocation.Method, values));
            }
            else
            {
                // TODO: Use all observed matchers, not just the last one!
                var lastMatch = matches[matches.Count - 1];

                var matchers     = new Expression[arguments.Length];
                var valueIndex   = arguments.Length - 1;
                var propertyType = setter.GetParameters()[valueIndex].ParameterType;

                // If the value matcher is not equal to the property
                // type (i.e. prop is int?, but you use It.IsAny<int>())
                // add a cast.
                if (lastMatch.RenderExpression.Type != propertyType)
                {
                    values[valueIndex] = Expression.Convert(lastMatch.RenderExpression, propertyType);
                }
                else
                {
                    values[valueIndex] = lastMatch.RenderExpression;
                }

                matchers[valueIndex] = new MatchExpression(lastMatch);

                for (int i = 0; i < arguments.Length - 1; i++)
                {
                    // Add the index value for the property indexer
                    values[i] = GetValueExpression(arguments[i], parameters[i].ParameterType);
                    // TODO: No matcher supported now for the index
                    matchers[i] = values[i];
                }

                var lambda = Expression.Lambda(
                    typeof(Action <>).MakeGenericType(x.Type),
                    Expression.Call(x, invocation.Method, values),
                    x);

                return(new SetupSetImplResult(target, lambda, invocation.Method, matchers));
            }
        }