public void MethodMissing(object source, MethodMissingParameters missingParameters)
        {
            var dynamicObject = source as DynamicObject;
            if (dynamicObject == null)
                return;

            var arguments = (missingParameters.Arguments ?? new object[0]);
            var target = dynamicObject.Target;

            var candidateMethods = _extensionMethods.AsFuzzyList();

            // Match the method name
            candidateMethods.AddCriteria(m => m.Name == missingParameters.MethodName, CriteriaType.Critical);

            // Match the number of method parameters (including the 'this' parameter)
            var expectedArgumentLength = arguments.Length + 1;
            candidateMethods.AddCriteria(m => m.GetParameters().Length == expectedArgumentLength, CriteriaType.Critical);

            Func<MethodBase, int, Type, bool> matchesParameterType = (method, index, type) =>
            {
                var parameters = method.GetParameters();
                var parameter = index < parameters.Length ? parameters[index] : null;
                return parameter != null && type.IsAssignableFrom(parameter.ParameterType);
            };

            var targetType = target.GetType();

            // Generic extension methods are not supported
            candidateMethods.AddCriteria(m => !m.IsGenericMethodDefinition, CriteriaType.Critical);

            // Match the first parameter type (the 'this' argument)
            candidateMethods.AddCriteria(m => matchesParameterType(m, 0, targetType), CriteriaType.Critical);

            // Match the remaining arguments
            var parameterIndex = 1;
            foreach (var arg in arguments)
            {
                if (arg == null)
                    continue;

                var argumentType = arg.GetType();
                var index = parameterIndex;
                candidateMethods.AddCriteria(m => matchesParameterType(m, index, argumentType), CriteriaType.Critical);
                parameterIndex++;
            }

            var bestMatch = candidateMethods.BestMatch();
            if (bestMatch == null)
                return;

            var matchingMethod = bestMatch.Item;

            // Combine the arguments with the 'this' target
            var extensionMethodArguments = new List<object> { target };
            extensionMethodArguments.AddRange(arguments);

            var returnValue = matchingMethod.Invoke(null, extensionMethodArguments.ToArray());
            missingParameters.ReturnValue = returnValue;
            missingParameters.Handled = true;
        }
        public void MethodMissing(object source,
                                  MethodMissingParameters missingParameters)
        {
            // The current method name must match the given method name
            if (_methodName != missingParameters.MethodName)
            {
                return;
            }

            var builder = new PredicateBuilder();

            if (missingParameters.Arguments != null)
            {
                builder.RuntimeArguments.AddRange(missingParameters.Arguments);
            }

            builder.MatchRuntimeArguments = true;

            // Match the criteria against the target delegate
            var items       = new List <MethodInfo>(new[] { _target.Method });
            var searchItems = items.AsFuzzyList();

            // Determine if the signature is compatible
            builder.AddPredicates(searchItems);
            var match = searchItems.BestMatch();

            if (match == null)
            {
                return;
            }

            // If the signature is compatible, then execute the method
            var targetMethod = _target.Method;

            object result = null;

            try
            {
                result = targetMethod.Invoke(_target.Target, missingParameters.Arguments);
                missingParameters.Handled = true;
            }
            catch (TargetInvocationException ex)
            {
                missingParameters.Handled = false;
                throw ex.InnerException;
            }


            missingParameters.ReturnValue = result;
        }
        public void MethodMissing(object source,
                                  MethodMissingParameters missingParameters)
        {
            var builder = new PredicateBuilder();

            // The current method name must match the given method name
            if (_methodName != missingParameters.MethodName)
                return;

            if (missingParameters.Arguments != null)
                builder.RuntimeArguments.AddRange(missingParameters.Arguments);

            builder.MatchRuntimeArguments = true;

            Predicate<MethodInfo> finderPredicate = builder.CreatePredicate();
            var finder = new FuzzyFinder<MethodInfo>();
            finder.Tolerance = .66;

            // Match the criteria against the target delegate
            var searchList = new List<MethodInfo>(new[] {_target.Method});

            // Determine if the signature is compatible
            MethodInfo match = finder.Find(finderPredicate, searchList);
            if (match == null)
                return;

            // If the signature is compatible, then execute the method
            MethodInfo targetMethod = _target.Method;

            object result = null;
            try
            {
                result = targetMethod.Invoke(_target.Target, missingParameters.Arguments);
                missingParameters.Handled = true;
            }
            catch (TargetInvocationException ex)
            {
                missingParameters.Handled = false;
                throw ex.InnerException;
            }


            missingParameters.ReturnValue = result;
        }
        internal object ExecuteMethodMissing(string methodName, object[] args, ref bool handled)
        {
            if (_handlers.Count == 0)
            {
                throw new MethodNotFoundException(
                          string.Format("Method '{0}' not found on type '{1}",
                                        methodName, Target.GetType().FullName));
            }

            // Emulate Ruby's MethodMissing behavior
            // so that methods can be added to this
            // class at runtime
            var missingParameters =
                new MethodMissingParameters(methodName, _target, args);

            // Recently added handlers take priority
            var handlers = new List <IMethodMissingCallback>(_handlers);

            handlers.Reverse();

            // Fire the event until a handler is found
            foreach (var callback in handlers)
            {
                callback.MethodMissing(this, missingParameters);
                if (missingParameters.Handled)
                {
                    break;
                }
            }


            if (missingParameters.Handled == false)
            {
                throw new MethodNotFoundException(
                          string.Format("Method '{0}' not found on type '{1}",
                                        methodName, Target.GetType().FullName));
            }

            handled = missingParameters.Handled;

            return(missingParameters.ReturnValue);
        }
        public void MethodMissing(object source, MethodMissingParameters missingParameters)
        {
            var    handled = false;
            object result  = null;

            try
            {
                result  = Methods[missingParameters.MethodName](missingParameters.Arguments);
                handled = true;
            }
            catch (Exception ex)
            {
                handled = false;
            }
            missingParameters.Handled = handled;

            if (handled)
            {
                missingParameters.ReturnValue = result;
            }
        }
示例#6
0
        public void MethodMissing(object source, MethodMissingParameters missingParameters)
        {
            var dynamicObject = source as DynamicObject;

            if (dynamicObject == null)
            {
                return;
            }

            var arguments = (missingParameters.Arguments ?? new object[0]);
            var target    = dynamicObject.Target;

            var candidateMethods = _extensionMethods.AsFuzzyList();

            // Match the method name
            candidateMethods.AddCriteria(m => m.Name == missingParameters.MethodName, CriteriaType.Critical);

            // Match the number of method parameters (including the 'this' parameter)
            var expectedArgumentLength = arguments.Length + 1;

            candidateMethods.AddCriteria(m => m.GetParameters().Length == expectedArgumentLength, CriteriaType.Critical);

            Func <MethodBase, int, Type, bool> matchesParameterType = (method, index, type) =>
            {
                var parameters = method.GetParameters();
                var parameter  = index < parameters.Length ? parameters[index] : null;
                return(parameter != null && type.IsAssignableFrom(parameter.ParameterType));
            };

            var targetType = target.GetType();

            // Generic extension methods are not supported
            candidateMethods.AddCriteria(m => !m.IsGenericMethodDefinition, CriteriaType.Critical);

            // Match the first parameter type (the 'this' argument)
            candidateMethods.AddCriteria(m => matchesParameterType(m, 0, targetType), CriteriaType.Critical);

            // Match the remaining arguments
            var parameterIndex = 1;

            foreach (var arg in arguments)
            {
                if (arg == null)
                {
                    continue;
                }

                var argumentType = arg.GetType();
                var index        = parameterIndex;
                candidateMethods.AddCriteria(m => matchesParameterType(m, index, argumentType), CriteriaType.Critical);
                parameterIndex++;
            }

            var bestMatch = candidateMethods.BestMatch();

            if (bestMatch == null)
            {
                return;
            }

            var matchingMethod = bestMatch.Item;

            // Combine the arguments with the 'this' target
            var extensionMethodArguments = new List <object> {
                target
            };

            extensionMethodArguments.AddRange(arguments);

            var returnValue = matchingMethod.Invoke(null, extensionMethodArguments.ToArray());

            missingParameters.ReturnValue = returnValue;
            missingParameters.Handled     = true;
        }