internal static MethodCandidate InferGenericMethod(ApplicableCandidate /*!*/ candidate, ActualArguments /*!*/ actualArgs) { OverloadInfo target = candidate.Method.Overload; Assert.NotNull(target); Debug.Assert(target.IsGenericMethodDefinition); Debug.Assert(target.IsGenericMethod && target.ContainsGenericParameters); List <DynamicMetaObject /*!*/> args = GetAllArguments(candidate, actualArgs); if (args == null) { return(null); } Dictionary <Type, List <Type> > dependencies = GetDependencyMapping(target); Type[] genArgs = GetSortedGenericArguments(target, dependencies); Dictionary <Type, ArgumentInputs> inputs = GetArgumentToInputMapping(candidate.Method, args); // now process the inputs var binding = new Dictionary <Type, Type>(); var restrictions = new Dictionary <DynamicMetaObject, BindingRestrictions>(); bool noMethod = false; foreach (Type t in genArgs) { if (!inputs.TryGetValue(t, out ArgumentInputs inps)) { continue; } Type bestType = inps.GetBestType(candidate.Method.Resolver, binding, restrictions); if (bestType == null) { // we conflict with possible constraints noMethod = true; break; } } if (!noMethod) { // finally build a new MethodCandidate for the generic method genArgs = GetGenericArgumentsForInferedMethod(target, binding); if (genArgs == null) { // not all types we're inferred return(null); } OverloadInfo newMethod = target.MakeGenericMethod(genArgs); List <ParameterWrapper> newWrappers = CreateNewWrappers(candidate.Method, newMethod, target); List <ArgBuilder> argBuilders = CreateNewArgBuilders(candidate.Method, newMethod); if (argBuilders == null) { // one or more arg builders don't support type inference return(null); } if (restrictions.Count == 0) { restrictions = null; } // create the new method candidate return(candidate.Method.ReplaceMethod(newMethod, newWrappers, argBuilders, restrictions)); } return(null); }
private static List <DynamicMetaObject> GetAllArguments(ApplicableCandidate candidate, ActualArguments actualArgs) { List <DynamicMetaObject> args = new List <DynamicMetaObject>(); for (int i = 0; i < actualArgs.Count; i++) { int index = candidate.ArgumentBinding.ArgumentToParameter(i); if (index < actualArgs.Arguments.Count) { args.Add(actualArgs.Arguments[index]); } else { args.Add(actualArgs.NamedArguments[index - actualArgs.Arguments.Count]); } } return(args); }
internal static MethodCandidate InferGenericMethod(ApplicableCandidate/*!*/ candidate, ActualArguments/*!*/ actualArgs) { OverloadInfo target = candidate.Method.Overload; Assert.NotNull(target); Debug.Assert(target.IsGenericMethodDefinition); Debug.Assert(target.IsGenericMethod && target.ContainsGenericParameters); List<DynamicMetaObject/*!*/> args = GetAllArguments(candidate, actualArgs); if (args == null) { return null; } Dictionary<Type, List<Type>> dependencies = GetDependencyMapping(target); Type[] genArgs = GetSortedGenericArguments(target, dependencies); Dictionary<Type, ArgumentInputs> inputs = GetArgumentToInputMapping(candidate.Method, args); // now process the inputs var binding = new Dictionary<Type, Type>(); var restrictions = new Dictionary<DynamicMetaObject, BindingRestrictions>(); bool noMethod = false; foreach (Type t in genArgs) { ArgumentInputs inps; if (!inputs.TryGetValue(t, out inps)) { continue; } Type bestType = inps.GetBestType(candidate.Method.Resolver, binding, restrictions); if (bestType == null) { // we conflict with possible constraints noMethod = true; break; } } if (!noMethod) { // finally build a new MethodCandidate for the generic method genArgs = GetGenericArgumentsForInferedMethod(target, binding); if (genArgs == null) { // not all types we're inferred return null; } OverloadInfo newMethod = target.MakeGenericMethod(genArgs); List<ParameterWrapper> newWrappers = CreateNewWrappers(candidate.Method, newMethod, target); List<ArgBuilder> argBuilders = CreateNewArgBuilders(candidate.Method, newMethod); if (argBuilders == null) { // one or more arg builders don't support type inference return null; } if (restrictions.Count == 0) { restrictions = null; } // create the new method candidate return candidate.Method.ReplaceMethod(newMethod, newWrappers, argBuilders, restrictions); } return null; }
/// <summary> /// Resolves a method overload and returns back a BindingTarget. /// /// The BindingTarget can then be tested for the success or particular type of /// failure that prevents the method from being called. If successfully bound the BindingTarget /// contains a list of argument meta-objects with additional restrictions that ensure the selection /// of the particular overload. /// </summary> public BindingTarget ResolveOverload(string methodName, IList<MethodBase> methods, NarrowingLevel minLevel, NarrowingLevel maxLevel) { ContractUtils.RequiresNotNullItems(methods, "methods"); ContractUtils.Requires(minLevel <= maxLevel); if (_candidateSets != null) { throw new InvalidOperationException("Overload resolver cannot be reused."); } _methodName = methodName; _minLevel = minLevel; _maxLevel = maxLevel; // step 1: IList<DynamicMetaObject> namedArgs; GetNamedArguments(out namedArgs, out _argNames); // uses arg names: BuildCandidateSets(methods); // uses target sets: int preSplatLimit, postSplatLimit; GetSplatLimits(out preSplatLimit, out postSplatLimit); // step 2: _actualArguments = CreateActualArguments(namedArgs, _argNames, preSplatLimit, postSplatLimit); if (_actualArguments == null) { return new BindingTarget(methodName, BindingResult.InvalidArguments); } // steps 3, 4: var candidateSet = GetCandidateSet(); if (candidateSet != null && !candidateSet.IsParamsDictionaryOnly()) { return MakeBindingTarget(candidateSet); } // step 5: return new BindingTarget(methodName, _actualArguments.VisibleCount, GetExpectedArgCounts()); }
private static List<DynamicMetaObject> GetAllArguments(ApplicableCandidate candidate, ActualArguments actualArgs) { List<DynamicMetaObject> args = new List<DynamicMetaObject>(); for (int i = 0; i < actualArgs.Count; i++) { int index = candidate.ArgumentBinding.ArgumentToParameter(i); if (index < actualArgs.Arguments.Count) { args.Add(actualArgs.Arguments[index]); } else { args.Add(actualArgs.NamedArguments[index - actualArgs.Arguments.Count]); } } return args; }