Skip to content

Commit c384044

Browse files
Added more reflection types
1 parent 72c9506 commit c384044

File tree

2 files changed

+78
-17
lines changed

2 files changed

+78
-17
lines changed

src/Reflector/IsType.cs

+41-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Diagnostics.CodeAnalysis;
33
using System.Reflection;
44
using System.Runtime.CompilerServices;
5+
using System.Text;
56

67
namespace VReflector;
78

@@ -57,28 +58,25 @@ public static bool RecordClass(Type type)
5758
if (type == null || !type.IsClass)
5859
return false;
5960

60-
bool hasCompilerGeneratedToString = type
61-
.GetMethod("ToString")
62-
?.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false)
63-
?.Any() == true;
64-
65-
bool hasEqualityContract = type
66-
?.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)
67-
?.Any(p => p.Name == "EqualityContract") == true;
68-
69-
return hasCompilerGeneratedToString && hasEqualityContract;
61+
return type.GetMethod("<Clone>$", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) is { } &&
62+
type.GetProperty("EqualityContract", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)?
63+
.GetMethod?.IsDecoratedWith<CompilerGeneratedAttribute>() == true;
7064
}
7165
public static bool RecordStruct(Type type)
7266
{
7367
if (type == null || !type.IsValueType || type.IsPrimitive)
7468
return false;
7569

76-
bool hasCompilerGeneratedToString = type
77-
.GetMethod("ToString")
78-
?.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false)
79-
.Any() == true;
80-
81-
return hasCompilerGeneratedToString;
70+
return type.BaseType == typeof(ValueType) &&
71+
type.GetMethod("PrintMembers", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, null,
72+
new Type[] { typeof(StringBuilder) }, null) is { } &&
73+
type.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly, null,
74+
new Type[] { type, type }, null)?
75+
.IsDecoratedWith<CompilerGeneratedAttribute>() == true;
76+
}
77+
public static bool KeyValuePair(Type type)
78+
{
79+
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>);
8280
}
8381
public static bool Enum(Type type) => type?.GetTypeInfo()?.BaseType == typeof(Enum);
8482
public static bool Nullable(Type? type) => type is null || type.IsClass || System.Nullable.GetUnderlyingType(type) != null;
@@ -107,6 +105,32 @@ public static bool Anonymous(Type type)
107105
type.GetCustomAttributes(false).Any(a => a is CompilerGeneratedAttribute) &&
108106
type.Name.StartsWith("<>") && type.IsClass;
109107
}
108+
private static bool IsTuple(Type type)
109+
{
110+
if (type == null || !type.IsGenericType)
111+
{
112+
return false;
113+
}
114+
115+
Type openType = type.GetGenericTypeDefinition();
116+
117+
return openType == typeof(ValueTuple<>)
118+
|| openType == typeof(ValueTuple<,>)
119+
|| openType == typeof(ValueTuple<,,>)
120+
|| openType == typeof(ValueTuple<,,,>)
121+
|| openType == typeof(ValueTuple<,,,,>)
122+
|| openType == typeof(ValueTuple<,,,,,>)
123+
|| openType == typeof(ValueTuple<,,,,,,>)
124+
|| (openType == typeof(ValueTuple<,,,,,,,>) && IsTuple(type.GetGenericArguments()[7]))
125+
|| openType == typeof(Tuple<>)
126+
|| openType == typeof(Tuple<,>)
127+
|| openType == typeof(Tuple<,,>)
128+
|| openType == typeof(Tuple<,,,>)
129+
|| openType == typeof(Tuple<,,,,>)
130+
|| openType == typeof(Tuple<,,,,,>)
131+
|| openType == typeof(Tuple<,,,,,,>)
132+
|| (openType == typeof(Tuple<,,,,,,,>) && IsTuple(type.GetGenericArguments()[7]));
133+
}
110134
public static bool ReadonlyStruct(Type type)
111135
{
112136
return type != null && Struct(type) && type.GetCustomAttributes(typeof(IsReadOnlyAttribute), false).Any();
@@ -242,7 +266,7 @@ public static bool Memory(Type type, [NotNullWhen(true)] out Type? elementType)
242266
elementType = null;
243267
return false;
244268
}
245-
public static bool ReadOnlyMemory( Type type)
269+
public static bool ReadOnlyMemory(Type type)
246270
{
247271
if (GenericType(type) && type.GetGenericTypeDefinition().FullName == "System.ReadOnlyMemory`1")
248272
{

src/Reflector/ReflectionExtensions.cs

+37
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,29 @@ public static bool SetIsAllowed(this PropertyInfo pInfo, bool checkNonPublicSett
324324
{
325325
return type?.GetEvents(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(e => e.AddMethod.IsPublic || e.AddMethod.IsFamily).ToArray();
326326
}
327+
public static MethodInfo? GetExplicitConversionOperator(this Type type, Type sourceType, Type targetType)
328+
{
329+
return type
330+
.GetConversionOperators(sourceType, targetType, name => name is "op_Explicit")
331+
.SingleOrDefault();
332+
}
333+
334+
public static MethodInfo? GetImplicitConversionOperator(this Type type, Type sourceType, Type targetType)
335+
{
336+
return type
337+
.GetConversionOperators(sourceType, targetType, name => name is "op_Implicit")
338+
.SingleOrDefault();
339+
}
340+
public static bool IsIndexer(this PropertyInfo member)
341+
{
342+
return member.GetIndexParameters().Length != 0;
343+
}
344+
345+
public static bool IsDecoratedWith<TAttribute>(this MemberInfo type)
346+
where TAttribute : Attribute
347+
{
348+
return Attribute.IsDefined(type, typeof(TAttribute), inherit: false);
349+
}
327350
public static FieldInfo[]? GetPublicAndProtectedStaticFields(this Type type)
328351
{
329352

@@ -861,6 +884,20 @@ private static string GetMemberReturnTypes(Type type, string genericSepratorStar
861884
}
862885
}
863886
private static string GetName(string? name) => name?.Split('`')[0] ?? string.Empty;
887+
private static IEnumerable<MethodInfo> GetConversionOperators(this Type type, Type sourceType, Type targetType,
888+
Func<string, bool> predicate)
889+
{
890+
return type
891+
.GetMethods()
892+
.Where(m =>
893+
m.IsPublic
894+
&& m.IsStatic
895+
&& m.IsSpecialName
896+
&& m.ReturnType == targetType
897+
&& predicate(m.Name)
898+
&& m.GetParameters() is { Length: 1 } parameters
899+
&& parameters[0].ParameterType == sourceType);
900+
}
864901

865902
#endregion Private Members
866903
}

0 commit comments

Comments
 (0)