private MethodResolver CreateMethodResolver() { MethodResolver resolver = new MethodResolver { MethodName = this.MethodName, RunAsynchronously = this.RunAsynchronously, TargetType = this.TargetType, TargetObject = this.TargetObject, GenericTypeArguments = this.GenericTypeArguments, Parameters = this.Parameters, Result = _resultArgument, Parent = this }; if (this.Result != null) { resolver.ResultType = this.Result.ArgumentType; } else { resolver.ResultType = typeof(object); } return(resolver); }
private MethodBase FindMatch(MethodBase[] methodCandidates, BindingFlags bindingAttr, Type[] types, ParameterModifier[] modifiers) { // Try the default binder first. Never gives false positive, but will fail to detect methods w/ parameter array because // it will not expand the formal parameter list when checking against actual parameters. MethodBase result = Type.DefaultBinder.SelectMethod(bindingAttr, methodCandidates, types, modifiers); // Could be false negative, check for parameter array and if so condense it back to an array before re-checking. if (result == null) { foreach (MethodBase method in methodCandidates) { MethodInfo methodInfo = method as MethodInfo; ParameterInfo[] formalParams = methodInfo.GetParameters(); if (MethodResolver.HaveParameterArray(formalParams)) // Check if the last parameter of method is marked w/ "params" attribute { Type elementType = formalParams[formalParams.Length - 1].ParameterType.GetElementType(); bool allCompatible = true; // There could be more actual parameters than formal parameters, because the formal parameter is a params T'[] for some T'. // So, check that each actual parameter starting at position [formalParams.Length - 1] is compatible with T'. for (int i = formalParams.Length - 1; i < types.Length - 1; i++) { if (!TypeHelper.AreTypesCompatible(types[i], elementType)) { allCompatible = false; break; } } if (!allCompatible) { continue; } // Condense the actual parameter back to an array. Type[] typeArray = new Type[formalParams.Length]; for (int i = 0; i < typeArray.Length - 1; i++) { typeArray[i] = types[i]; } typeArray[typeArray.Length - 1] = elementType.MakeArrayType(); // Recheck the condensed array MethodBase newFound = Type.DefaultBinder.SelectMethod(bindingAttr, new MethodBase[] { methodInfo }, typeArray, modifiers); if (result != null && newFound != null) { string type = newFound.ReflectedType.Name; string name = newFound.Name; string bindingType = bindingAttr == staticBindingFlags ? staticString : instanceString; throw FxTrace.Exception.AsError(new AmbiguousMatchException(SR.DuplicateMethodFound(type, bindingType, name, this.parentActivity.DisplayName))); } else { result = newFound; } } } } return(result); }
protected override void CacheMetadata(CodeActivityMetadata metadata) { Collection <RuntimeArgument> arguments = new Collection <RuntimeArgument>(); Type targetObjectType = TypeHelper.ObjectType; if (this.TargetObject != null) { targetObjectType = this.TargetObject.ArgumentType; } RuntimeArgument targetObjectArgument = new RuntimeArgument("TargetObject", targetObjectType, ArgumentDirection.In); metadata.Bind(this.TargetObject, targetObjectArgument); arguments.Add(targetObjectArgument); Type resultType = TypeHelper.ObjectType; if (this.Result != null) { resultType = this.Result.ArgumentType; } _resultArgument = new RuntimeArgument("Result", resultType, ArgumentDirection.Out); metadata.Bind(this.Result, _resultArgument); arguments.Add(_resultArgument); // Parameters are named according to MethodInfo name if DetermineMethodInfo // succeeds, otherwise arbitrary names are used. _methodResolver = CreateMethodResolver(); _methodResolver.DetermineMethodInfo(metadata, s_funcCache, s_locker, ref _methodExecutor); _methodResolver.RegisterParameters(arguments); metadata.SetArgumentsCollection(arguments); _methodResolver.Trace(); if (_methodExecutor != null) { _methodExecutor.Trace(this); } }