예제 #1
0
        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);
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }