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);
PropertyInfo property = TypeExtensions.GetProperty(typeFromHandle, "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> func = Expression.Lambda<Func<MemberInfo, MemberInfo, bool>>(Expression.Equal(Expression.Property(parameterExpression, property), Expression.Property(parameterExpression2, property)), new ParameterExpression[2] {
parameterExpression,
parameterExpression2
}).Compile();
bool result = func(m1, m2);
s_MemberEquivalence = func;
return result;
}
} catch {
}
return (s_MemberEquivalence = ((MemberInfo m1param, MemberInfo m2param) => m1param.IsEquivalentTo(m2param)))(m1, m2);
};
public static bool IsEquivalentTo(this Type t1, Type t2)
{
return (object)t1 == t2;
}
public static bool IsNullableType(this Type type)
{
if (type.IsConstructedGenericType)
return (object)type.GetGenericTypeDefinition() == typeof(Nullable<>);
return false;
}
public static TypeCode GetTypeCode(this Type type)
{
if ((object)type == null)
return TypeCode.Empty;
if ((object)type == typeof(bool))
return TypeCode.Boolean;
if ((object)type == typeof(char))
return TypeCode.Char;
if ((object)type == typeof(sbyte))
return TypeCode.SByte;
if ((object)type == typeof(byte))
return TypeCode.Byte;
if ((object)type == typeof(short))
return TypeCode.Int16;
if ((object)type == typeof(ushort))
return TypeCode.UInt16;
if ((object)type == typeof(int))
return TypeCode.Int32;
if ((object)type == typeof(uint))
return TypeCode.UInt32;
if ((object)type == typeof(long))
return TypeCode.Int64;
if ((object)type == typeof(ulong))
return TypeCode.UInt64;
if ((object)type == typeof(float))
return TypeCode.Single;
if ((object)type == typeof(double))
return TypeCode.Double;
if ((object)type == typeof(decimal))
return TypeCode.Decimal;
if ((object)type == typeof(DateTime))
return TypeCode.DateTime;
if ((object)type == typeof(string))
return TypeCode.String;
if (type.GetTypeInfo().get_IsEnum())
return Enum.GetUnderlyingType(type).GetTypeCode();
return TypeCode.Object;
}
public static bool IsEquivalentTo(this MemberInfo mi1, MemberInfo mi2)
{
if ((object)mi1 == null || (object)mi2 == null) {
if ((object)mi1 == null)
return (object)mi2 == null;
return false;
}
if (mi1.Equals(mi2))
return true;
if (mi1 is MethodInfo && mi2 is MethodInfo) {
MethodInfo method3 = mi1 as MethodInfo;
MethodInfo method2 = mi2 as MethodInfo;
if (method3.IsGenericMethod != method2.IsGenericMethod)
return false;
if (method3.IsGenericMethod) {
method3 = method3.GetGenericMethodDefinition();
method2 = method2.GetGenericMethodDefinition();
if (method3.GetGenericArguments().Length != method2.GetGenericArguments().Length)
return false;
}
ParameterInfo[] parameters;
ParameterInfo[] parameters2;
if ((object)method3 != method2 && method3.Name == method2.Name && method3.DeclaringType.IsGenericallyEqual(method2.DeclaringType) && method3.ReturnType.IsGenericallyEquivalentTo(method2.ReturnType, method3, method2) && (parameters = method3.GetParameters()).Length == (parameters2 = method2.GetParameters()).Length)
return parameters.Zip(parameters2, (ParameterInfo pi1, ParameterInfo pi2) => pi1.IsEquivalentTo(pi2, method3, method2)).All((bool x) => x);
return false;
}
if (mi1 is ConstructorInfo && mi2 is ConstructorInfo) {
ConstructorInfo ctor3 = mi1 as ConstructorInfo;
ConstructorInfo ctor2 = mi2 as ConstructorInfo;
ParameterInfo[] parameters3;
ParameterInfo[] parameters4;
if ((object)ctor3 != ctor2 && ctor3.DeclaringType.IsGenericallyEqual(ctor2.DeclaringType) && (parameters3 = ctor3.GetParameters()).Length == (parameters4 = ctor2.GetParameters()).Length)
return parameters3.Zip(parameters4, (ParameterInfo pi1, ParameterInfo pi2) => pi1.IsEquivalentTo(pi2, ctor3, ctor2)).All((bool x) => x);
return false;
}
if (mi1 is PropertyInfo && mi2 is PropertyInfo) {
PropertyInfo propertyInfo = mi1 as PropertyInfo;
PropertyInfo propertyInfo2 = mi2 as PropertyInfo;
if ((object)propertyInfo != propertyInfo2 && propertyInfo.Name == propertyInfo2.Name && propertyInfo.DeclaringType.IsGenericallyEqual(propertyInfo2.DeclaringType) && propertyInfo.PropertyType.IsGenericallyEquivalentTo(propertyInfo2.PropertyType, propertyInfo, propertyInfo2) && PropertyInfoExtensions.GetGetMethod(propertyInfo, true).IsEquivalentTo(PropertyInfoExtensions.GetGetMethod(propertyInfo2, true)))
return PropertyInfoExtensions.GetSetMethod(propertyInfo, true).IsEquivalentTo(PropertyInfoExtensions.GetSetMethod(propertyInfo2, true));
return false;
}
return false;
}
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 ((object)t1 == null || (object)t2 == null) {
if ((object)t1 == null)
return (object)t2 == 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 ((object)t1.GetTypeInfo().get_DeclaringMethod() == null && member1.DeclaringType.Equals(t1.GetTypeInfo().DeclaringType)) {
if ((object)t2.GetTypeInfo().get_DeclaringMethod() != null || !member2.DeclaringType.Equals(t2.GetTypeInfo().DeclaringType))
return t1.IsTypeParameterEquivalentToTypeInst(t2, member2);
} else if ((object)t2.GetTypeInfo().get_DeclaringMethod() == null && member2.DeclaringType.Equals(t2.GetTypeInfo().DeclaringType)) {
return t2.IsTypeParameterEquivalentToTypeInst(t1, member1);
}
return false;
}
return t1.IsTypeParameterEquivalentToTypeInst(t2, member2);
}
if (t2.IsGenericParameter)
return t2.IsTypeParameterEquivalentToTypeInst(t1, member1);
if (t1.GetTypeInfo().get_IsGenericType() && t2.GetTypeInfo().get_IsGenericType()) {
Type[] genericArguments = TypeExtensions.GetGenericArguments(t1);
Type[] genericArguments2 = TypeExtensions.GetGenericArguments(t2);
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 ((object)typeParam.GetTypeInfo().get_DeclaringMethod() != null) {
if (!(member is MethodBase))
return false;
MethodBase methodBase = (MethodBase)member;
int genericParameterPosition = typeParam.GetTypeInfo().get_GenericParameterPosition();
Type[] array = methodBase.IsGenericMethod ? methodBase.GetGenericArguments() : null;
if (array != null && array.Length > genericParameterPosition)
return array[genericParameterPosition].Equals(typeInst);
return false;
}
return TypeExtensions.GetGenericArguments(member.DeclaringType)[typeParam.GetTypeInfo().get_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;
}
}
}