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; } }
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; }