/// <summary> /// Resolves an extension method by arguments. /// </summary> public static MethodWrapper ResolveExtensionMethod(ExtensionMethodResolver resolver, Type type, string name, Type[] argTypes, Type[] hints, LambdaResolver lambdaResolver) { var method = resolver.ResolveExtensionMethod(type, name, argTypes); var args = method.GetParameters(); var info = new MethodWrapper { Name = name, Type = method.DeclaringType, MethodInfo = method, IsStatic = true, IsVirtual = false, ReturnType = method.ReturnType, ArgumentTypes = args.Select(p => p.ParameterType).ToArray(), IsPartiallyApplied = IsPartiallyApplied(argTypes), IsVariadic = IsVariadic(method), }; if (method.IsGenericMethod) { var expectedTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); var genericDefs = method.GetGenericArguments(); var extMethodArgs = argTypes.ToList(); extMethodArgs.Insert(0, type); var genericValues = GenericHelper.ResolveMethodGenericsByArgs( expectedTypes, extMethodArgs.ToArray(), genericDefs, hints, lambdaResolver ); info.GenericArguments = genericValues; info.MethodInfo = info.MethodInfo.MakeGenericMethod(genericValues); info.ReturnType = GenericHelper.ApplyGenericArguments(info.ReturnType, genericDefs, genericValues); info.ArgumentTypes = expectedTypes.Select(t => GenericHelper.ApplyGenericArguments(t, genericDefs, genericValues)).ToArray(); } else if (hints != null) { error(CompilerMessages.GenericArgsToNonGenericMethod, name); } return(info); }
/// <summary> /// Resolves a method by its name and argument types. If generic arguments are passed, they are also applied. /// Generic arguments whose values can be inferred from argument types can be skipped. /// </summary> public static MethodWrapper ResolveMethod(Type type, string name, Type[] argTypes, Type[] hints, LambdaResolver lambdaResolver) { var mw = new MethodWrapper { Name = name, Type = type }; try { var method = ResolveMethodByArgs( getMethodsByName(type, name), m => m.GetParameters().Select(p => p.ParameterType).ToArray(), IsVariadic, argTypes ); var mInfo = method.Method; if (mInfo.IsGenericMethod) { var genericDefs = mInfo.GetGenericArguments(); var genericValues = GenericHelper.ResolveMethodGenericsByArgs(method.ArgumentTypes, argTypes, genericDefs, hints); mInfo = mInfo.MakeGenericMethod(genericValues); mw.GenericArguments = genericValues; } else if (hints != null) { error(CompilerMessages.GenericArgsToNonGenericMethod, name); } mw.MethodInfo = mInfo; mw.IsStatic = mInfo.IsStatic; mw.IsVirtual = mInfo.IsVirtual; mw.ArgumentTypes = method.ArgumentTypes; mw.ReturnType = mInfo.ReturnType; mw.IsPartiallyApplied = IsPartiallyApplied(argTypes); mw.IsVariadic = IsVariadic(mInfo); return(mw); } catch (NotSupportedException) { if (!type.IsGenericType) { throw new KeyNotFoundException(); } var genType = type.GetGenericTypeDefinition(); var genMethod = ResolveMethodByArgs( getMethodsByName(genType, name), m => m.GetParameters().Select(p => GenericHelper.ApplyGenericArguments(p.ParameterType, type, false)).ToArray(), IsVariadic, argTypes ); var mInfoOriginal = genMethod.Method; var declType = resolveActualDeclaringType(type, mInfoOriginal.DeclaringType); var mInfo = getMethodVersionForType(declType, mInfoOriginal); if (mInfoOriginal.IsGenericMethod) { var genericDefs = mInfoOriginal.GetGenericArguments(); var genericValues = GenericHelper.ResolveMethodGenericsByArgs(genMethod.ArgumentTypes, argTypes, genericDefs, hints, lambdaResolver); mInfo = mInfo.MakeGenericMethod(genericValues); var totalGenericDefs = genericDefs.Union(genType.GetGenericTypeDefinition().GetGenericArguments()).ToArray(); var totalGenericValues = genericValues.Union(type.GetGenericArguments()).ToArray(); mw.GenericArguments = genericValues; mw.ReturnType = GenericHelper.ApplyGenericArguments(mInfoOriginal.ReturnType, totalGenericDefs, totalGenericValues); mw.ArgumentTypes = mInfoOriginal.GetParameters().Select(p => GenericHelper.ApplyGenericArguments(p.ParameterType, totalGenericDefs, totalGenericValues)).ToArray(); } else { if (hints != null) { error(CompilerMessages.GenericArgsToNonGenericMethod, name); } mw.ArgumentTypes = mInfoOriginal.GetParameters().Select(p => GenericHelper.ApplyGenericArguments(p.ParameterType, type)).ToArray(); mw.ReturnType = GenericHelper.ApplyGenericArguments(mInfoOriginal.ReturnType, type, false); } mw.MethodInfo = mInfo; mw.IsStatic = mInfoOriginal.IsStatic; mw.IsVirtual = mInfoOriginal.IsVirtual; mw.IsPartiallyApplied = IsPartiallyApplied(argTypes); mw.IsVariadic = IsVariadic(mInfoOriginal); } return(mw); }