Example #1
0
            /// <summary>
            /// Finds the best match among the candidates.
            /// </summary>
            /// <param name="binder">The binder that is requesting the match.</param>
            /// <param name="args">The args passed in to the invocation.</param>
            /// <param name="genericArgs">The generic args if any.</param>
            /// <param name="candidates">The candidate methods to use for the match..</param>
            /// <param name="assignableFrom">if set to <c>true</c>, uses a more lax matching approach for arguments, with IsAssignableFrom instead of == for arg type.</param>
            private IInvocable FindBestMatchImpl(DynamicMetaObjectBinder binder, object[] args, int genericArgs, IEnumerable <IInvocable> candidates, bool assignableFrom)
            {
                dynamic dynamicBinder = binder.AsDynamicReflection();

                for (int i = 0; i < args.Length; i++)
                {
                    var index = i;
                    if (args[index] != null)
                    {
                        if (assignableFrom)
                        {
                            candidates = candidates.Where(x => x.Parameters[index].ParameterType.IsAssignableFrom(GetArgumentType(args[index])));
                        }
                        else
                        {
                            candidates = candidates.Where(x => x.Parameters[index].ParameterType == GetArgumentType(args[index]));
                        }
                    }

                    IEnumerable enumerable = dynamicBinder.ArgumentInfo;
                    // The binder has the extra argument info for the "this" parameter at the beginning.
                    if (enumerable.Cast <object>().ToList()[index + 1].AsDynamicReflection().IsByRef)
                    {
                        candidates = candidates.Where(x => x.Parameters[index].ParameterType.IsByRef);
                    }

                    if (genericArgs > 0)
                    {
                        candidates = candidates.Where(x => x.IsGeneric && x.GenericParameters == genericArgs);
                    }
                }

                return(candidates.FirstOrDefault());
            }
Example #2
0
            /// <summary>
            /// Finds the best match among the candidates.
            /// </summary>
            /// <param name="binder">The binder that is requesting the match.</param>
            /// <param name="args">The args passed in to the invocation.</param>
            /// <param name="genericArgs">The generic args if any.</param>
            /// <param name="candidates">The candidate methods to use for the match..</param>
            /// <param name="matching">if set to <c>MatchingStyle.AssignableFrom</c>, uses a more lax matching approach for arguments, with IsAssignableFrom instead of == for arg type,
            /// and <c>MatchingStyle.GenericTypeHint</c> tries to use the generic arguments as type hints if they match the # of args.</param>
            private IInvocable FindBestMatchImpl(DynamicMetaObjectBinder binder, object[] args, List <Type> genericArgs, IEnumerable <IInvocable> candidates, MatchingStyle matching)
            {
                dynamic dynamicBinder = binder.AsDynamicReflection();

                for (int i = 0; i < args.Length; i++)
                {
                    var index = i;
                    if (args[index] != null)
                    {
                        switch (matching)
                        {
                        case MatchingStyle.ExactType:
                            candidates = candidates.Where(x => x.Parameters[index].ParameterType.IsAssignableFrom(GetArgumentType(args[index])));
                            break;

                        case MatchingStyle.AssignableFrom:
                            candidates = candidates.Where(x => x.Parameters[index].ParameterType.IsEquivalentTo(GetArgumentType(args[index])));
                            break;

                        case MatchingStyle.ExactTypeGenericHint:
                            candidates = candidates.Where(x => x.Parameters.Count == genericArgs.Count &&
                                                          x.Parameters[index].ParameterType.IsEquivalentTo(genericArgs[index]));
                            break;

                        case MatchingStyle.AssignableFromGenericHint:
                            candidates = candidates.Where(x => x.Parameters.Count == genericArgs.Count &&
                                                          x.Parameters[index].ParameterType.IsAssignableFrom(genericArgs[index]));
                            break;

                        default:
                            break;
                        }
                    }

                    IEnumerable enumerable = dynamicBinder.ArgumentInfo;
                    // The binder has the extra argument info for the "this" parameter at the beginning.
                    if (enumerable.Cast <object>().ToList()[index + 1].AsDynamicReflection().IsByRef)
                    {
                        candidates = candidates.Where(x => x.Parameters[index].ParameterType.IsByRef);
                    }

                    // Only filter by matching generic argument count if the generics isn't being used as parameter type hints.
                    if (genericArgs.Count > 0 && matching != MatchingStyle.AssignableFromGenericHint && matching != MatchingStyle.ExactTypeGenericHint)
                    {
                        candidates = candidates.Where(x => x.IsGeneric && x.GenericParameters == genericArgs.Count);
                    }
                }

                return(candidates.FirstOrDefault());
            }
Example #3
0
            private IInvocable FindBestMatch(DynamicMetaObjectBinder binder, string memberName, object[] args)
            {
                var finalArgs       = args.Where(x => !(x is TypeParameter)).ToArray();
                var genericTypeArgs = new List <Type>();

                if (binder is InvokeBinder || binder is InvokeMemberBinder)
                {
                    IEnumerable typeArgs = binder.AsDynamicReflection().TypeArguments;
                    genericTypeArgs.AddRange(typeArgs.Cast <Type>());
                    genericTypeArgs.AddRange(args.OfType <TypeParameter>().Select(x => x.Type));
                }

                var method = FindBestMatch(binder, finalArgs, genericTypeArgs.Count, this.targetType
                                           .GetMethods(flags)
                                           .Where(x => x.Name == memberName && x.GetParameters().Length == finalArgs.Length)
                                           .Select(x => new MethodInvocable(x)));

                if (method == null)
                {
                    // Fallback to explicitly implemented members.
                    method = FindBestMatch(binder, finalArgs, genericTypeArgs.Count, this.targetType
                                           .GetInterfaces()
                                           .SelectMany(
                                               iface => this.targetType
                                               .GetInterfaceMap(iface)
                                               .TargetMethods.Select(x => new { Interface = iface, Method = x }))
                                           .Where(x =>
                                                  x.Method.GetParameters().Length == finalArgs.Length &&
                                                  x.Method.Name.Replace(x.Interface.FullName.Replace('+', '.') + ".", "") == memberName)
                                           .Select(x => (IInvocable) new MethodInvocable(x.Method))
                                           .Concat(this.targetType.GetConstructors(flags)
                                                   .Where(x => x.Name == memberName && x.GetParameters().Length == finalArgs.Length)
                                                   .Select(x => new ConstructorInvocable(x)))
                                           .Distinct());
                }

                var methodInvocable = method as MethodInvocable;

                if (method != null && methodInvocable != null && methodInvocable.Method.IsGenericMethodDefinition)
                {
                    method = new MethodInvocable(methodInvocable.Method.MakeGenericMethod(genericTypeArgs.ToArray()));
                }

                return(method);
            }