static private BuilderExpectsSingleParameter ( ArgBuilder builder ) : bool | ||
builder | ArgBuilder | |
Результат | bool |
/// <summary> /// Maps out parameters to return args and ref parameters to ones that don't accept StrongBox. /// </summary> private void MapParameterReduceByRef(ParameterInfo pi) { Debug.Assert(_returnArgs != null); // TODO: // Is this reduction necessary? What if // 1) we had an implicit conversion StrongBox<T> -> T& and // 2) all out parameters were treated as optional StrongBox<T> parameters? (if not present we return the result in a return value) int indexForArgBuilder = 0; int nameIndex = -1; if (!pi.IsOutParameter()) { nameIndex = _argNames.IndexOf(pi.Name); if (nameIndex == -1) { indexForArgBuilder = _argIndex++; } } ArgBuilder ab; if (pi.IsOutParameter()) { _returnArgs.Add(_arguments.Count); ab = new OutArgBuilder(pi); } else if (pi.ParameterType.IsByRef) { // if the parameter is marked as [In] it is not returned. if ((pi.Attributes & (ParameterAttributes.In | ParameterAttributes.Out)) != ParameterAttributes.In) { _returnArgs.Add(_arguments.Count); } _parameters.Add(new ParameterWrapper(pi, pi.ParameterType.GetElementType(), pi.Name, ParameterBindingFlags.None)); ab = new ReturnReferenceArgBuilder(pi, indexForArgBuilder); } else { ab = AddSimpleParameterMapping(pi, indexForArgBuilder); } if (nameIndex == -1) { _arguments.Add(ab); } else { Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab)); _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex)); } }
public void MapParameter(ParameterInfo pi) { int indexForArgBuilder; int nameIndex = _argNames.IndexOf(pi.Name); if (nameIndex == -1) { // positional argument, we simply consume the next argument indexForArgBuilder = _argIndex++; } else { // keyword argument, we just tell the simple arg builder to consume arg 0. // KeywordArgBuilder will then pass in the correct single argument based // upon the actual argument number provided by the user. indexForArgBuilder = 0; } // if the parameter is default we need to build a default arg builder and then // build a reduced method at the end. if (!pi.IsMandatory()) { // We need to build the default builder even if we have a parameter for it already to // get good consistency of our error messages. But consider a method like // def foo(a=1, b=2) and the user calls it as foo(b=3). Then adding the default // value breaks an otherwise valid call. This is because we only generate MethodCandidates // filling in the defaults from right to left (so the method - 1 arg requires a, // and the method minus 2 args requires b). So we only add the default if it's // a positional arg or we don't already have a default value. if (nameIndex == -1 || !_hasDefaults) { _defaultArguments.Add(new DefaultArgBuilder(pi)); _hasDefaults = true; } else { _defaultArguments.Add(null); } } else if (_defaultArguments.Count > 0) { // non-contigious default parameter _defaultArguments.Add(null); } ArgBuilder ab; if (pi.ParameterType.IsByRef) { _hasByRef = true; Type elementType = pi.ParameterType.GetElementType(); Type refType = typeof(StrongBox <>).MakeGenericType(elementType); _parameters.Add(new ParameterWrapper(pi, refType, pi.Name, ParameterBindingFlags.ProhibitNull)); ab = new ReferenceArgBuilder(pi, elementType, refType, indexForArgBuilder); } else if (pi.Position == 0 && _overload.IsExtension) { _parameters.Add(new ParameterWrapper(pi, pi.ParameterType, pi.Name, ParameterBindingFlags.IsHidden)); ab = new SimpleArgBuilder(pi, pi.ParameterType, indexForArgBuilder, false, false); } else { ab = AddSimpleParameterMapping(pi, indexForArgBuilder); } if (nameIndex == -1) { _arguments.Add(ab); } else { Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab)); _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex)); } }