<PackageReference Include="Microsoft.CSharp" Version="4.7.0-preview1.19504.10" />

RuntimeBinderExtensions

using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Microsoft.CSharp.RuntimeBinder { internal static class RuntimeBinderExtensions { private static Func<MemberInfo, MemberInfo, bool> s_MemberEquivalence = delegate(MemberInfo m1, MemberInfo m2) { try { Type typeFromHandle = typeof(MemberInfo); MethodInfo method = typeFromHandle.GetMethod("HasSameMetadataDefinitionAs", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.ExactBinding, null, new Type[1] { typeof(MemberInfo) }, null); if (method != (MethodInfo)null) { Func<MemberInfo, MemberInfo, bool> func = (Func<MemberInfo, MemberInfo, bool>)method.CreateDelegate(typeof(Func<MemberInfo, MemberInfo, bool>)); try { bool result = func(m1, m2); s_MemberEquivalence = func; return result; } catch { } } PropertyInfo property = typeFromHandle.GetProperty("MetadataToken", typeof(int), Array.Empty<Type>()); if ((object)property != null && property.CanRead) { ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle); ParameterExpression parameterExpression2 = Expression.Parameter(typeFromHandle); Func<MemberInfo, MemberInfo, bool> func2 = Expression.Lambda<Func<MemberInfo, MemberInfo, bool>>(Expression.Equal(Expression.Property(parameterExpression, property), Expression.Property(parameterExpression2, property)), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); bool result2 = func2(m1, m2); s_MemberEquivalence = func2; return result2; } } catch { } return (s_MemberEquivalence = ((MemberInfo m1param, MemberInfo m2param) => m1param.IsEquivalentTo(m2param)))(m1, m2); }; public static bool IsNullableType(this Type type) { if (type.IsConstructedGenericType) return type.GetGenericTypeDefinition() == typeof(Nullable<>); return false; } public static bool IsEquivalentTo(this MemberInfo mi1, MemberInfo mi2) { if (mi1 == (MemberInfo)null || mi2 == (MemberInfo)null) { if (mi1 == (MemberInfo)null) return mi2 == (MemberInfo)null; return false; } if (mi1.Equals(mi2)) return true; MethodInfo methodInfo = mi1 as MethodInfo; if ((object)methodInfo != null) { MethodInfo methodInfo2 = mi2 as MethodInfo; if ((object)methodInfo2 == null || methodInfo.IsGenericMethod != methodInfo2.IsGenericMethod) return false; if (methodInfo.IsGenericMethod) { methodInfo = methodInfo.GetGenericMethodDefinition(); methodInfo2 = methodInfo2.GetGenericMethodDefinition(); if (methodInfo.GetGenericArguments().Length != methodInfo2.GetGenericArguments().Length) return false; } if (methodInfo != methodInfo2 && methodInfo.CallingConvention == methodInfo2.CallingConvention && methodInfo.Name == methodInfo2.Name && methodInfo.DeclaringType.IsGenericallyEqual(methodInfo2.DeclaringType) && methodInfo.ReturnType.IsGenericallyEquivalentTo(methodInfo2.ReturnType, methodInfo, methodInfo2)) return methodInfo.AreParametersEquivalent(methodInfo2); return false; } ConstructorInfo constructorInfo = mi1 as ConstructorInfo; if ((object)constructorInfo != null) { ConstructorInfo constructorInfo2 = mi2 as ConstructorInfo; if ((object)constructorInfo2 != null && constructorInfo != constructorInfo2 && constructorInfo.CallingConvention == constructorInfo2.CallingConvention && constructorInfo.DeclaringType.IsGenericallyEqual(constructorInfo2.DeclaringType)) return constructorInfo.AreParametersEquivalent(constructorInfo2); return false; } PropertyInfo propertyInfo = mi1 as PropertyInfo; if ((object)propertyInfo != null) { PropertyInfo propertyInfo2 = mi2 as PropertyInfo; if ((object)propertyInfo2 != null && propertyInfo != propertyInfo2 && propertyInfo.Name == propertyInfo2.Name && propertyInfo.DeclaringType.IsGenericallyEqual(propertyInfo2.DeclaringType) && propertyInfo.PropertyType.IsGenericallyEquivalentTo(propertyInfo2.PropertyType, propertyInfo, propertyInfo2) && propertyInfo.GetGetMethod(true).IsEquivalentTo(propertyInfo2.GetGetMethod(true))) return propertyInfo.GetSetMethod(true).IsEquivalentTo(propertyInfo2.GetSetMethod(true)); } return false; } private static bool AreParametersEquivalent(this MethodBase method1, MethodBase method2) { ParameterInfo[] parameters = method1.GetParameters(); ParameterInfo[] parameters2 = method2.GetParameters(); if (parameters.Length != parameters2.Length) return false; for (int i = 0; i < parameters.Length; i++) { if (!parameters[i].IsEquivalentTo(parameters2[i], method1, method2)) return false; } return true; } private static bool IsEquivalentTo(this ParameterInfo pi1, ParameterInfo pi2, MethodBase method1, MethodBase method2) { if (pi1 == null || pi2 == null) { if (pi1 == null) return pi2 == null; return false; } if (pi1.Equals(pi2)) return true; return pi1.ParameterType.IsGenericallyEquivalentTo(pi2.ParameterType, method1, method2); } private static bool IsGenericallyEqual(this Type t1, Type t2) { if (t1 == (Type)null || t2 == (Type)null) { if (t1 == (Type)null) return t2 == (Type)null; return false; } if (t1.Equals(t2)) return true; if (t1.IsConstructedGenericType || t2.IsConstructedGenericType) { Type type = t1.IsConstructedGenericType ? t1.GetGenericTypeDefinition() : t1; Type o = t2.IsConstructedGenericType ? t2.GetGenericTypeDefinition() : t2; return type.Equals(o); } return false; } private static bool IsGenericallyEquivalentTo(this Type t1, Type t2, MemberInfo member1, MemberInfo member2) { if (t1.Equals(t2)) return true; if (t1.IsGenericParameter) { if (t2.IsGenericParameter) { if (t1.DeclaringMethod == (MethodBase)null && member1.DeclaringType.Equals(t1.DeclaringType)) { if (!(t2.DeclaringMethod == (MethodBase)null) || !member2.DeclaringType.Equals(t2.DeclaringType)) return t1.IsTypeParameterEquivalentToTypeInst(t2, member2); } else if (t2.DeclaringMethod == (MethodBase)null && member2.DeclaringType.Equals(t2.DeclaringType)) { return t2.IsTypeParameterEquivalentToTypeInst(t1, member1); } return false; } return t1.IsTypeParameterEquivalentToTypeInst(t2, member2); } if (t2.IsGenericParameter) return t2.IsTypeParameterEquivalentToTypeInst(t1, member1); if (t1.IsGenericType && t2.IsGenericType) { Type[] genericArguments = t1.GetGenericArguments(); Type[] genericArguments2 = t2.GetGenericArguments(); if (genericArguments.Length == genericArguments2.Length) { if (t1.IsGenericallyEqual(t2)) return genericArguments.Zip(genericArguments2, (Type ta1, Type ta2) => ta1.IsGenericallyEquivalentTo(ta2, member1, member2)).All((bool x) => x); return false; } } if (t1.IsArray && t2.IsArray) { if (t1.GetArrayRank() == t2.GetArrayRank()) return t1.GetElementType().IsGenericallyEquivalentTo(t2.GetElementType(), member1, member2); return false; } if ((t1.IsByRef && t2.IsByRef) || (t1.IsPointer && t2.IsPointer)) return t1.GetElementType().IsGenericallyEquivalentTo(t2.GetElementType(), member1, member2); return false; } private static bool IsTypeParameterEquivalentToTypeInst(this Type typeParam, Type typeInst, MemberInfo member) { if (typeParam.DeclaringMethod != (MethodBase)null) { if (!(member is MethodBase)) return false; MethodBase methodBase = (MethodBase)member; int genericParameterPosition = typeParam.GenericParameterPosition; Type[] array = methodBase.IsGenericMethod ? methodBase.GetGenericArguments() : null; if (array != null && array.Length > genericParameterPosition) return array[genericParameterPosition].Equals(typeInst); return false; } return member.DeclaringType.GetGenericArguments()[typeParam.GenericParameterPosition].Equals(typeInst); } public static bool HasSameMetadataDefinitionAs(this MemberInfo mi1, MemberInfo mi2) { if (mi1.Module.Equals(mi2.Module)) return s_MemberEquivalence(mi1, mi2); return false; } public static string GetIndexerName(this Type type) { string typeIndexerName = GetTypeIndexerName(type); if (typeIndexerName == null && type.IsInterface) { Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { typeIndexerName = GetTypeIndexerName(type2); if (typeIndexerName != null) break; } } return typeIndexerName; } private static string GetTypeIndexerName(Type type) { string name = type.GetCustomAttribute<DefaultMemberAttribute>()?.MemberName; if (name != null && type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Any(delegate(PropertyInfo p) { if (p.Name == name) return p.GetIndexParameters().Length != 0; return false; })) return name; return null; } } }