/// <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 parameters obtained from the /// public properties of the supplied <paramref name="sample"/> object. /// 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> /// <returns>The result of the invocation.</returns> public static object TryCallMethod( this object obj, string methodName, bool mustUseAllParameters, object sample ) { Type sourceType = sample.GetType(); var sourceInfo = new SourceInfo( sourceType ); var paramValues = sourceInfo.GetParameterValues( sample ); return obj.TryCallMethod( methodName, mustUseAllParameters, sourceInfo.ParamNames, sourceInfo.ParamTypes, paramValues ); }
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; }
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> /// 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 ) { Type sourceType = sample.GetType(); var sourceInfo = new SourceInfo( sourceType ); bool isStatic = obj is Type; string[] names = sourceInfo.ParamNames; Type[] types = sourceInfo.ParamTypes; object[] values = sourceInfo.GetParameterValues( sample ); 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( methodPool, mustUseAllParameters, names, types, values ); return isStatic ? map.Invoke( values ) : map.Invoke( obj, values ); }
/// <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) { Type sourceType = sample.GetType(); var sourceInfo = new SourceInfo(sourceType); bool isStatic = obj is Type; string[] names = sourceInfo.ParamNames; Type[] types = sourceInfo.ParamTypes; object[] values = sourceInfo.GetParameterValues(sample); 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(methodPool, mustUseAllParameters, names, types, values); return(isStatic ? map.Invoke(values) : map.Invoke(obj, values)); }
/// <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() ?? Constants.EmptyStringArray; object[] values = parameters.Values.ToArray() ?? Constants.EmptyObjectArray; Type[] types = values.ToTypeArray() ?? Type.EmptyTypes; bool isStatic = obj is Type; Type type = isStatic ? obj as Type : obj.GetType(); SourceInfo 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)); }
/// <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 ); }
private static int[] GetSampleHashes() { var sources = new object[] { new { }, new { Id = 42 }, new { Name = "Scar" }, new { Id = 42, Name = "Scar" }, new { Id = 42, Birthday = DateTime.Now }, new { Id = 42, Name = "Scar", Birthday = DateTime.Now, Dummy = 0 } }; int index = 0; var infos = new SourceInfo[ sources.Length ]; Array.ForEach( sources, s => { infos[ index++ ] = SourceInfo.CreateFromType( s.GetType() ); } ); index = 0; int[] hashes = new int[ sources.Length ]; Array.ForEach( infos, i => { hashes[ index++ ] = i.GetHashCode(); } ); return hashes; }