Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
        /// <summary>
        /// Creates an instance of the given <paramref name="type"/> using the public properties of the
        /// supplied <paramref name="sample"/> object as input.
        /// This method will try to determine the least-cost route to constructing the instance, which
        /// implies mapping as many properties as possible to constructor parameters. Remaining properties
        /// on the source are mapped to properties on the created instance or ignored if none matches.
        /// TryCreateInstance is very liberal and attempts to convert values that are not otherwise
        /// considered compatible, such as between strings and enums or numbers, Guids and byte[], etc.
        /// </summary>
        /// <returns>An instance of <paramref name="type"/>.</returns>
        public static object TryCreateInstance(this Type type, object sample)
        {
            Type       sourceType = sample.GetType();
            SourceInfo sourceInfo = sourceInfoCache.Get(sourceType);

            if (sourceInfo == null)
            {
                sourceInfo = new SourceInfo(sourceType);
                sourceInfoCache.Insert(sourceType, sourceInfo);
            }
            object[]  paramValues = sourceInfo.GetParameterValues(sample);
            MethodMap map         = MapFactory.PrepareInvoke(type, sourceInfo.ParamNames, sourceInfo.ParamTypes, paramValues);

            return(map.Invoke(paramValues));
        }
        /// <summary>
        /// Creates an instance of the given <paramref name="type"/> using the supplied parameter information as input.
        /// This method will try to determine the least-cost route to constructing the instance, which
        /// implies mapping as many properties as possible to constructor parameters. Remaining properties
        /// on the source are mapped to properties on the created instance or ignored if none matches.
        /// TryCreateInstance is very liberal and attempts to convert values that are not otherwise
        /// considered compatible, such as between strings and enums or numbers, Guids and byte[], etc.
        /// </summary>
        /// <param name="type">The type of which an instance should be created.</param>
        /// <param name="parameterNames">The names of the supplied parameters.</param>
        /// <param name="parameterTypes">The types of the supplied parameters.</param>
        /// <param name="parameterValues">The values of the supplied parameters.</param>
        /// <returns>An instance of <paramref name="type"/>.</returns>
        public static object TryCreateInstance(this Type type, string[] parameterNames, Type[] parameterTypes,
                                               object[] parameterValues)
        {
            var names  = parameterNames ?? new string[0];
            var types  = parameterTypes ?? new Type[0];
            var values = parameterValues ?? new object[0];

            if (names.Length != values.Length || names.Length != types.Length)
            {
                throw new ArgumentException("Mismatching name, type and value arrays (must be of identical length).");
            }
            MethodMap map = MapFactory.PrepareInvoke(type, names, types, values);

            return(map.Invoke(values));
        }
Exemple #5
0
        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);
            }
            StringBuilder 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());
        }
Exemple #6
0
        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);
            }
            StringBuilder 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());
        }
Exemple #7
0
        /// <summary>
        /// Obtains a list of all methods with the given <paramref name="methodName"/> on the given
        /// <paramref name="obj" />, and invokes the best match for the supplied parameters.
        /// TryCallMethod is very liberal and attempts to convert values that are not otherwise
        /// considered compatible, such as between strings and enums or numbers, Guids and byte[16], etc.
        /// </summary>
        /// <param name="obj">The type of which an instance should be created.</param>
        /// <param name="methodName">The name of the overloaded methods.</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="parameterNames">The names of the supplied parameters.</param>
        /// <param name="parameterTypes">The types of the supplied parameters.</param>
        /// <param name="parameterValues">The values of the supplied parameters.</param>
        /// <returns>The result of the invocation.</returns>
        public static object TryCallMethod(this object obj, string methodName, bool mustUseAllParameters,
                                           string[] parameterNames, Type[] parameterTypes, object[] parameterValues)
        {
            bool isStatic = obj is Type;
            var  type     = isStatic ? obj as Type : obj.GetType();
            var  names    = parameterNames ?? new string[0];
            var  types    = parameterTypes ?? new Type[0];
            var  values   = parameterValues ?? new object[0];

            if (names.Length != values.Length || names.Length != types.Length)
            {
                throw new ArgumentException("Mismatching name, type and value arrays (must be of identical length).");
            }
            MethodMap map = MapFactory.DetermineBestMethodMatch(type.Methods(methodName).Cast <MethodBase>(), mustUseAllParameters, names, types, values);

            return(isStatic ? map.Invoke(values) : map.Invoke(obj, values));
        }