private ParameterWrapper CreateParameterWrapper(ParameterInfo info) { bool isParamArray = Overload.IsParamArray(info.Position); bool isParamDict = !isParamArray && Overload.IsParamDictionary(info.Position); bool prohibitsNullItems = (isParamArray || isParamDict) && Overload.ProhibitsNullItems(info.Position); return(new ParameterWrapper( info, info.ParameterType, info.Name, (Overload.ProhibitsNull(info.Position) ? ParameterBindingFlags.ProhibitNull : 0) | (prohibitsNullItems ? ParameterBindingFlags.ProhibitNullItems : 0) | (isParamArray ? ParameterBindingFlags.IsParamArray : 0) | (isParamDict ? ParameterBindingFlags.IsParamDictionary : 0) )); }
/// <summary> /// Builds a new MethodCandidate which takes count arguments and the provided list of keyword arguments. /// /// The basic idea here is to figure out which parameters map to params or a dictionary params and /// fill in those spots w/ extra ParameterWrapper's. /// </summary> internal MethodCandidate MakeParamsExtended(int count, IList <string> names) { Debug.Assert(Overload.IsVariadic); List <ParameterWrapper> newParameters = new List <ParameterWrapper>(count); // keep track of which named args map to a real argument, and which ones // map to the params dictionary. List <string> unusedNames = new List <string>(names); List <int> unusedNameIndexes = new List <int>(); for (int i = 0; i < unusedNames.Count; i++) { unusedNameIndexes.Add(i); } // if we don't have a param array we'll have a param dict which is type object ParameterWrapper paramsArrayParameter = null; int paramsArrayIndex = -1; for (int i = 0; i < _parameters.Count; i++) { ParameterWrapper parameter = _parameters[i]; if (parameter.IsParamsArray) { paramsArrayParameter = parameter; paramsArrayIndex = i; } else { int j = unusedNames.IndexOf(parameter.Name); if (j != -1) { unusedNames.RemoveAt(j); unusedNameIndexes.RemoveAt(j); } newParameters.Add(parameter); } } if (paramsArrayIndex != -1) { ParameterWrapper expanded = paramsArrayParameter.Expand(); while (newParameters.Count < (count - unusedNames.Count)) { newParameters.Insert(System.Math.Min(paramsArrayIndex, newParameters.Count), expanded); } } if (_paramsDict != null) { var flags = (Overload.ProhibitsNullItems(_paramsDict.ParameterInfo.Position) ? ParameterBindingFlags.ProhibitNull : 0) | (_paramsDict.IsHidden ? ParameterBindingFlags.IsHidden : 0); foreach (string name in unusedNames) { newParameters.Add(new ParameterWrapper(_paramsDict.ParameterInfo, typeof(object), name, flags)); } } else if (unusedNames.Count != 0) { // unbound kw args and no where to put them, can't call... // TODO: We could do better here because this results in an incorrect arg # error message. return(null); } // if we have too many or too few args we also can't call if (count != newParameters.Count) { return(null); } return(MakeParamsExtended(unusedNames.ToArray(), unusedNameIndexes.ToArray(), newParameters)); }