ReflectionExtensions
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace System.Text.Json.Reflection
{
internal static class ReflectionExtensions
{
private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2";
private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2";
private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary";
public const string CreateRangeMethodName = "CreateRange";
public static Type GetCompatibleGenericBaseClass(this Type type, Type baseType, Type objectType = null, bool sourceGenType = false)
{
if ((object)objectType == null)
objectType = typeof(object);
Type type2 = type;
while (type2 != (Type)null && type2 != typeof(object)) {
if (type2.IsGenericType) {
Type genericTypeDefinition = type2.GetGenericTypeDefinition();
if (genericTypeDefinition == baseType || (sourceGenType && OpenGenericTypesHaveSamePrefix(baseType, genericTypeDefinition)))
return type2;
}
type2 = type2.BaseType;
}
return null;
}
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "The 'interfaceType' must exist and so trimmer kept it. In which case It also kept it on any type which implements it. The below call to GetInterfaces may return fewer results when trimmed but it will return the 'interfaceType' if the type implemented it, even after trimming.")]
public static Type GetCompatibleGenericInterface(this Type type, Type interfaceType)
{
Type type2 = type;
if (type2.IsGenericType)
type2 = type2.GetGenericTypeDefinition();
if (type2 == interfaceType)
return type;
Type[] interfaces = type.GetInterfaces();
foreach (Type type3 in interfaces) {
if (type3.IsGenericType) {
Type genericTypeDefinition = type3.GetGenericTypeDefinition();
if (genericTypeDefinition == interfaceType)
return type3;
}
}
return null;
}
public static bool IsImmutableDictionaryType(this Type type, bool sourceGenType = false)
{
if (type.IsGenericType && type.Assembly.FullName.StartsWith("System.Collections.Immutable", StringComparison.Ordinal)) {
switch (GetBaseNameFromGenericType(type, sourceGenType)) {
case "System.Collections.Immutable.ImmutableDictionary`2":
case "System.Collections.Immutable.IImmutableDictionary`2":
case "System.Collections.Immutable.ImmutableSortedDictionary`2":
return true;
default:
return false;
}
}
return false;
}
public static bool IsImmutableEnumerableType(this Type type, bool sourceGenType = false)
{
if (type.IsGenericType && type.Assembly.FullName.StartsWith("System.Collections.Immutable", StringComparison.Ordinal)) {
switch (GetBaseNameFromGenericType(type, sourceGenType)) {
case "System.Collections.Immutable.ImmutableArray`1":
case "System.Collections.Immutable.ImmutableList`1":
case "System.Collections.Immutable.IImmutableList`1":
case "System.Collections.Immutable.ImmutableStack`1":
case "System.Collections.Immutable.IImmutableStack`1":
case "System.Collections.Immutable.ImmutableQueue`1":
case "System.Collections.Immutable.IImmutableQueue`1":
case "System.Collections.Immutable.ImmutableSortedSet`1":
case "System.Collections.Immutable.ImmutableHashSet`1":
case "System.Collections.Immutable.IImmutableSet`1":
return true;
default:
return false;
}
}
return false;
}
public static string GetImmutableDictionaryConstructingTypeName(this Type type, bool sourceGenType = false)
{
switch (GetBaseNameFromGenericType(type, sourceGenType)) {
case "System.Collections.Immutable.ImmutableDictionary`2":
case "System.Collections.Immutable.IImmutableDictionary`2":
return "System.Collections.Immutable.ImmutableDictionary";
case "System.Collections.Immutable.ImmutableSortedDictionary`2":
return "System.Collections.Immutable.ImmutableSortedDictionary";
default:
return null;
}
}
public static string GetImmutableEnumerableConstructingTypeName(this Type type, bool sourceGenType = false)
{
switch (GetBaseNameFromGenericType(type, sourceGenType)) {
case "System.Collections.Immutable.ImmutableArray`1":
return "System.Collections.Immutable.ImmutableArray";
case "System.Collections.Immutable.ImmutableList`1":
case "System.Collections.Immutable.IImmutableList`1":
return "System.Collections.Immutable.ImmutableList";
case "System.Collections.Immutable.ImmutableStack`1":
case "System.Collections.Immutable.IImmutableStack`1":
return "System.Collections.Immutable.ImmutableStack";
case "System.Collections.Immutable.ImmutableQueue`1":
case "System.Collections.Immutable.IImmutableQueue`1":
return "System.Collections.Immutable.ImmutableQueue";
case "System.Collections.Immutable.ImmutableSortedSet`1":
return "System.Collections.Immutable.ImmutableSortedSet";
case "System.Collections.Immutable.ImmutableHashSet`1":
case "System.Collections.Immutable.IImmutableSet`1":
return "System.Collections.Immutable.ImmutableHashSet";
default:
return null;
}
}
private static bool OpenGenericTypesHaveSamePrefix(Type t1, Type t2)
{
return t1.FullName == GetBaseNameFromGenericTypeDef(t2);
}
private static string GetBaseNameFromGenericType(Type genericType, bool sourceGenType)
{
Type genericTypeDefinition = genericType.GetGenericTypeDefinition();
if (!sourceGenType)
return genericTypeDefinition.FullName;
return GetBaseNameFromGenericTypeDef(genericTypeDefinition);
}
private static string GetBaseNameFromGenericTypeDef(Type genericTypeDef)
{
string fullName = genericTypeDef.FullName;
int length = fullName.IndexOf("`") + 2;
return fullName.Substring(0, length);
}
public static bool IsVirtual(this PropertyInfo propertyInfo)
{
if (propertyInfo != (PropertyInfo)null) {
if (!(propertyInfo.GetMethod?.IsVirtual ?? false))
return propertyInfo.SetMethod?.IsVirtual ?? false;
return true;
}
return false;
}
}
}