| File: System\Dynamic\Utils\TypeExtensions.cs | Web Access |
| Project: src\runtime\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Dynamic.Utils { // Extensions on System.Type and friends internal static class TypeExtensions { private static readonly CacheDict<MethodBase, ParameterInfo[]> s_paramInfoCache = new CacheDict<MethodBase, ParameterInfo[]>(75); /// <summary> /// Returns the matching method if the parameter types are reference /// assignable from the provided type arguments, otherwise null. /// </summary> public static MethodInfo? GetAnyStaticMethodValidated( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] this Type type, string name, Type[] types) { Debug.Assert(types != null); MethodInfo? method = type.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly, null, types, null); return method.MatchesArgumentTypes(types) ? method : null; } /// <summary> /// Returns true if the method's parameter types are reference assignable from /// the argument types, otherwise false. /// /// An example that can make the method return false is that /// typeof(double).GetMethod("op_Equality", ..., new[] { typeof(double), typeof(int) }) /// returns a method with two double parameters, which doesn't match the provided /// argument types. /// </summary> private static bool MatchesArgumentTypes(this MethodInfo? mi, Type[] argTypes) { Debug.Assert(argTypes != null); if (mi == null) { return false; } ParameterInfo[] ps = mi.GetParametersCached(); if (ps.Length != argTypes.Length) { return false; } for (int i = 0; i < ps.Length; i++) { if (!TypeUtils.AreReferenceAssignable(ps[i].ParameterType, argTypes[i])) { return false; } } return true; } public static Type GetReturnType(this MethodBase mi) => mi.IsConstructor ? mi.DeclaringType! : ((MethodInfo)mi).ReturnType; public static TypeCode GetTypeCode(this Type type) => Type.GetTypeCode(type); internal static ParameterInfo[] GetParametersCached(this MethodBase method) { CacheDict<MethodBase, ParameterInfo[]> pic = s_paramInfoCache; if (!pic.TryGetValue(method, out ParameterInfo[]? pis)) { pis = method.GetParameters(); if (!method.IsCollectible) { pic[method] = pis; } } return pis; } // Expression trees/compiler just use IsByRef, why do we need this? // (see LambdaCompiler.EmitArguments for usage in the compiler) internal static bool IsByRefParameter(this ParameterInfo pi) { // not using IsIn/IsOut properties as they are not available in Silverlight: if (pi.ParameterType.IsByRef) return true; return (pi.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out; } } }