private static MethodMap DetermineBestMatch(IEnumerable <MethodBase> methods, bool mustUseAllParameters, string[] paramNames, Type[] parameterTypes, object[] sampleParamValues) { MethodMap bestMap = null; foreach (MethodBase method in methods) { MethodMap map = CreateMap(method, paramNames, parameterTypes, sampleParamValues, mustUseAllParameters); if (map != null && map.IsValid) { bool isBetter = bestMap == null; isBetter |= map.IsPerfectMatch; isBetter |= bestMap != null && (map.Cost < bestMap.Cost || (map.Cost == bestMap.Cost && map.RequiredParameterCount > bestMap.RequiredParameterCount)); isBetter &= map.IsValid; if (isBetter) { bestMap = map; } } } if (bestMap != null) { bestMap.InitializeInvoker(); return(bestMap); } return(null); }
/// <summary> /// Invoke the best available match for the supplied parameters. If no method can be called /// using the supplied parameters, an exception is thrown. /// </summary> /// <param name="obj">The object on which to invoke a method.</param> /// <param name="mustUseAllParameters">Specifies whether all supplied parameters must be used in the /// invocation. Unless you know what you are doing you should pass true for this parameter.</param> /// <param name="sample">The object whose public properties will be used as parameters.</param> /// <returns>The return value of the invocation.</returns> public object Invoke(object obj, bool mustUseAllParameters, object sample) { if (obj == null || sample == null) { throw new ArgumentException("Missing or invalid argument: " + (obj == null ? "obj" : "sample")); } var sourceInfo = SourceInfo.CreateFromType(sample.GetType()); // check to see if we already have a map for best match MethodMap map = mapCache.Get(sourceInfo); object[] values = sourceInfo.GetParameterValues(sample); if (map == null) { string[] names = sourceInfo.ParamNames; Type[] types = sourceInfo.ParamTypes; if (names.Length != values.Length || names.Length != types.Length) { throw new ArgumentException("Mismatching name, type and value arrays (must be of identical length)."); } map = MapFactory.DetermineBestMethodMatch(methodPool, mustUseAllParameters, names, types, values); mapCache.Insert(sourceInfo, map); } bool isStatic = obj is Type; return(isStatic ? map.Invoke(values) : map.Invoke(obj, values)); }
public static MethodMap PrepareInvoke(Type type, string[] paramNames, Type[] parameterTypes, object[] sampleParamValues) { SourceInfo sourceInfo = new SourceInfo(type, paramNames, parameterTypes); MethodMap map = ctorMapCache.Get(sourceInfo); if (map == null) { map = DetermineBestConstructorMatch(type, paramNames, parameterTypes, sampleParamValues); ctorMapCache.Insert(sourceInfo, map); } return(map); }
internal static MethodMap DetermineBestConstructorMatch(Type type, string[] paramNames, Type[] parameterTypes, object[] sampleParamValues) { MethodMap map = DetermineBestMatch(type.GetConstructors(), false, paramNames, parameterTypes, sampleParamValues); if (map != null) { return(map); } var sb = new StringBuilder(); sb.AppendFormat("No constructor found for type {0} using parameters:{1}", type.Name, Environment.NewLine); sb.AppendFormat("{0}{1}", string.Join(", ", Enumerable.Range(0, paramNames.Length).Select(i => string.Format("{0}:{1}", paramNames[i], parameterTypes[i])).ToArray()), Environment.NewLine); throw new MissingMethodException(sb.ToString()); }
internal static MethodMap DetermineBestMethodMatch(IEnumerable <MethodBase> methods, bool mustUseAllParameters, string[] paramNames, Type[] parameterTypes, object[] sampleParamValues) { MethodMap map = DetermineBestMatch(methods, mustUseAllParameters, paramNames, parameterTypes, sampleParamValues); if (map != null) { return(map); } var sb = new StringBuilder(); sb.AppendFormat("No method found ({0} candidates examined) matching the parameters:{1}", methods.ToList().Count, Environment.NewLine); //sb.AppendFormat( "{0}{1}", Format( parameters, "=", ", " ), Environment.NewLine ); sb.AppendFormat("{0}{1}", string.Join(", ", Enumerable.Range(0, paramNames.Length).Select(i => string.Format("{0}:{1}", paramNames[i], parameterTypes[i])).ToArray()), Environment.NewLine); throw new MissingMethodException(sb.ToString()); }
/// <summary> /// Invoke the best available match for the supplied parameters. /// If no method can be called using the supplied parameters, an exception is thrown. /// </summary> /// <param name="obj">The object on which to invoke a method.</param> /// <param name="mustUseAllParameters">Specifies whether all supplied parameters must be used in the /// invocation. Unless you know what you are doing you should pass true for this parameter.</param> /// <param name="parameters">A dictionary of parameter name/value pairs.</param> /// <returns>The return value of the invocation.</returns> public object Invoke(object obj, bool mustUseAllParameters, Dictionary <string, object> parameters) { if (obj == null || parameters == null) { throw new ArgumentException("Missing or invalid argument: " + (obj == null ? "obj" : "parameters")); } string[] names = parameters.Keys.ToArray() ?? new string[0]; object[] values = parameters.Values.ToArray() ?? new object[0]; Type[] types = values.ToTypeArray() ?? new Type[0]; bool isStatic = obj is Type; var type = isStatic ? obj as Type : obj.GetType(); var sourceInfo = new SourceInfo(type, names, types); // check to see if we already have a map for best match MethodMap map = mapCache.Get(sourceInfo); if (map == null) { map = MapFactory.DetermineBestMethodMatch(methodPool, mustUseAllParameters, names, types, values); mapCache.Insert(sourceInfo, map); } return(isStatic ? map.Invoke(values) : map.Invoke(obj, values)); }