public object Invoke(IInvocationInfo invocationInfo) { var targetMethodName = _targetMethodName; var candidateMethods = typeof(TInterface).GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.Name == targetMethodName).ToArray(); var finder = new MethodBaseFinder <MethodInfo>(); var bestMatch = finder.GetBestMatch(candidateMethods, new MethodFinderContext(Option.Some(targetMethodName), invocationInfo.Arguments)); if (!bestMatch.HasValue) { throw new NotImplementedException($"Invocation error: Unable to find a method that is compatible with the '{targetMethodName}' method"); } // Match the signatures var matchingSignature = finder.GetBestMatch(new[] { _targetDelegateMethodSignature }, new MethodFinderContext(Option.None <string>(), invocationInfo.Arguments)); if (!matchingSignature.HasValue) { throw new NotImplementedException($"Invocation error: Unable to find a method that is compatible with the '{targetMethodName}' method"); } var result = _targetDelegateMethodSignature.Invoke(_targetDelegate.Target, invocationInfo.Arguments); return(result); }
public Option <object> Invoke(Option <string> methodName, params object[] arguments) { var candidateDelegates = (methodName.HasValue && _methods.ContainsKey(methodName.ValueOrFailure()) ? _methods[methodName.ValueOrFailure()].ToArray() : Enumerable.Empty <MulticastDelegate>()).ToArray(); var delegatesByMethod = candidateDelegates.ToDictionary(d => d.Method); var candidateMethods = candidateDelegates.Select(d => d.Method).ToArray(); var finder = new MethodBaseFinder <MethodInfo>(); // Note: The method name comparisons between delegates and the target method name have been skipped // because they will never match var bestMatch = finder.GetBestMatch(delegatesByMethod.Keys, string.Empty, arguments); // Fall back to a method with a MetaObject parameter as the first optional parameter, if it exists var methodArgs = new List <object>(arguments); if (!bestMatch.HasValue && candidateMethods.Any(m => m.IsFallbackMethod())) { var modifiedArgs = new List <object> { _owner }; modifiedArgs.AddRange(methodArgs); bestMatch = finder.GetBestMatch(delegatesByMethod.Keys, string.Empty, modifiedArgs); // Swap the method args and prepend // the owner instance if we have a match if (bestMatch.HasValue) { methodArgs = modifiedArgs; } } if (!bestMatch.HasValue) { return(Option.None <object>()); } var targetMethod = bestMatch.ValueOrFailure(); var targetDelegate = delegatesByMethod[targetMethod]; var returnValue = targetMethod.Invoke(targetDelegate.Target, methodArgs.ToArray()); return(Option.Some(returnValue)); }
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) { var finder = new MethodBaseFinder <MethodInfo>(); var context = new MethodFinderContext(Option.None <string>(), args); var delegatesByMethod = _delegates.ToDictionary(d => d.Method); var methods = delegatesByMethod.Keys; result = null; var bestMatch = finder.GetBestMatch(methods, context); if (!bestMatch.HasValue) { return(false); } var targetMethod = bestMatch.ValueOrFailure(); var targetDelegate = delegatesByMethod[targetMethod]; result = targetMethod.Invoke(targetDelegate.Target, args); return(true); }