@@ -24,11 +24,8 @@ internal static class TypeExtensions
2424 private static readonly ConcurrentDictionary < Type , bool > HasValueSemanticsCache = new ( ) ;
2525 private static readonly ConcurrentDictionary < Type , bool > TypeIsRecordCache = new ( ) ;
2626
27- private static readonly ConcurrentDictionary < ( Type Type , MemberVisibility Visibility ) , IEnumerable < PropertyInfo > >
28- NonPrivatePropertiesCache = new ( ) ;
29-
30- private static readonly ConcurrentDictionary < ( Type Type , MemberVisibility Visibility ) , IEnumerable < FieldInfo > >
31- NonPrivateFieldsCache = new ( ) ;
27+ private static readonly ConcurrentDictionary < ( Type Type , MemberVisibility Visibility ) , TypeMemberReflector >
28+ TypeMemberReflectorsCache = new ( ) ;
3229
3330 public static bool IsDecoratedWith < TAttribute > ( this Type type )
3431 where TAttribute : Attribute
@@ -221,143 +218,23 @@ public static FieldInfo FindField(this Type type, string fieldName)
221218
222219 public static IEnumerable < MemberInfo > GetNonPrivateMembers ( this Type typeToReflect , MemberVisibility visibility )
223220 {
224- return
225- GetNonPrivateProperties ( typeToReflect , visibility )
226- . Concat < MemberInfo > ( GetNonPrivateFields ( typeToReflect , visibility ) )
227- . ToArray ( ) ;
221+ return GetTypeReflectorFor ( typeToReflect , visibility ) . NonPrivateMembers ;
228222 }
229223
230224 public static IEnumerable < PropertyInfo > GetNonPrivateProperties ( this Type typeToReflect , MemberVisibility visibility )
231225 {
232- return NonPrivatePropertiesCache . GetOrAdd ( ( typeToReflect , visibility ) , static key =>
233- {
234- IEnumerable < PropertyInfo > query =
235- from propertyInfo in GetPropertiesFromHierarchy ( key . Type , key . Visibility )
236- where HasNonPrivateGetter ( propertyInfo )
237- where ! propertyInfo . IsIndexer ( )
238- select propertyInfo ;
239-
240- return query . ToArray ( ) ;
241- } ) ;
242- }
243-
244- private static IEnumerable < PropertyInfo > GetPropertiesFromHierarchy ( Type typeToReflect , MemberVisibility memberVisibility )
245- {
246- bool includeInternals = memberVisibility . HasFlag ( MemberVisibility . Internal ) ;
247-
248- return GetMembersFromHierarchy ( typeToReflect , type =>
249- {
250- return type
251- . GetProperties ( AllInstanceMembersFlag | BindingFlags . DeclaredOnly )
252- . Where ( property => property . GetMethod ? . IsPrivate == false )
253- . Where ( property => includeInternals || property . GetMethod is { IsAssembly : false , IsFamilyOrAssembly : false } )
254- . ToArray ( ) ;
255- } ) ;
226+ return GetTypeReflectorFor ( typeToReflect , visibility ) . NonPrivateProperties ;
256227 }
257228
258229 public static IEnumerable < FieldInfo > GetNonPrivateFields ( this Type typeToReflect , MemberVisibility visibility )
259230 {
260- return NonPrivateFieldsCache . GetOrAdd ( ( typeToReflect , visibility ) , static key =>
261- {
262- IEnumerable < FieldInfo > query =
263- from fieldInfo in GetFieldsFromHierarchy ( key . Type , key . Visibility )
264- where ! fieldInfo . IsPrivate
265- where ! fieldInfo . IsFamily
266- select fieldInfo ;
267-
268- return query . ToArray ( ) ;
269- } ) ;
270- }
271-
272- private static IEnumerable < FieldInfo > GetFieldsFromHierarchy ( Type typeToReflect , MemberVisibility memberVisibility )
273- {
274- bool includeInternals = memberVisibility . HasFlag ( MemberVisibility . Internal ) ;
275-
276- return GetMembersFromHierarchy ( typeToReflect , type =>
277- {
278- return type
279- . GetFields ( AllInstanceMembersFlag )
280- . Where ( field => ! field . IsPrivate )
281- . Where ( field => includeInternals || ( ! field . IsAssembly && ! field . IsFamilyOrAssembly ) )
282- . ToArray ( ) ;
283- } ) ;
284- }
285-
286- private static IEnumerable < TMemberInfo > GetMembersFromHierarchy < TMemberInfo > (
287- Type typeToReflect ,
288- Func < Type , IEnumerable < TMemberInfo > > getMembers )
289- where TMemberInfo : MemberInfo
290- {
291- if ( typeToReflect . IsInterface )
292- {
293- return GetInterfaceMembers ( typeToReflect , getMembers ) ;
294- }
295-
296- return GetClassMembers ( typeToReflect , getMembers ) ;
297- }
298-
299- private static List < TMemberInfo > GetInterfaceMembers < TMemberInfo > ( Type typeToReflect ,
300- Func < Type , IEnumerable < TMemberInfo > > getMembers )
301- where TMemberInfo : MemberInfo
302- {
303- List < TMemberInfo > members = new ( ) ;
304-
305- var considered = new List < Type > ( ) ;
306- var queue = new Queue < Type > ( ) ;
307- considered . Add ( typeToReflect ) ;
308- queue . Enqueue ( typeToReflect ) ;
309-
310- while ( queue . Count > 0 )
311- {
312- Type subType = queue . Dequeue ( ) ;
313-
314- foreach ( Type subInterface in subType . GetInterfaces ( ) )
315- {
316- if ( considered . Contains ( subInterface ) )
317- {
318- continue ;
319- }
320-
321- considered . Add ( subInterface ) ;
322- queue . Enqueue ( subInterface ) ;
323- }
324-
325- IEnumerable < TMemberInfo > typeMembers = getMembers ( subType ) ;
326-
327- IEnumerable < TMemberInfo > newPropertyInfos = typeMembers . Where ( x => ! members . Contains ( x ) ) ;
328-
329- members . InsertRange ( 0 , newPropertyInfos ) ;
330- }
331-
332- return members ;
333- }
334-
335- private static List < TMemberInfo > GetClassMembers < TMemberInfo > ( Type typeToReflect ,
336- Func < Type , IEnumerable < TMemberInfo > > getMembers )
337- where TMemberInfo : MemberInfo
338- {
339- List < TMemberInfo > members = new ( ) ;
340-
341- while ( typeToReflect != null )
342- {
343- foreach ( var memberInfo in getMembers ( typeToReflect ) )
344- {
345- if ( members . All ( mi => mi . Name != memberInfo . Name ) )
346- {
347- members . Add ( memberInfo ) ;
348- }
349- }
350-
351- typeToReflect = typeToReflect . BaseType ;
352- }
353-
354- return members ;
231+ return GetTypeReflectorFor ( typeToReflect , visibility ) . NonPrivateFields ;
355232 }
356233
357- private static bool HasNonPrivateGetter ( PropertyInfo propertyInfo )
234+ private static TypeMemberReflector GetTypeReflectorFor ( Type typeToReflect , MemberVisibility visibility )
358235 {
359- MethodInfo getMethod = propertyInfo . GetGetMethod ( nonPublic : true ) ;
360- return getMethod is { IsPrivate : false , IsFamily : false } ;
236+ return TypeMemberReflectorsCache . GetOrAdd ( ( typeToReflect , visibility ) ,
237+ static key => new TypeMemberReflector ( key . Type , key . Visibility ) ) ;
361238 }
362239
363240 /// <summary>
@@ -404,11 +281,6 @@ public static MethodInfo GetParameterlessMethod(this Type type, string methodNam
404281 return type . GetMethod ( methodName , Enumerable . Empty < Type > ( ) ) ;
405282 }
406283
407- public static bool HasParameterlessMethod ( this Type type , string methodName )
408- {
409- return type . GetParameterlessMethod ( methodName ) is not null ;
410- }
411-
412284 public static PropertyInfo FindPropertyByName ( this Type type , string propertyName )
413285 {
414286 return type . GetProperty ( propertyName , AllStaticAndInstanceMembersFlag ) ;
@@ -426,6 +298,11 @@ public static bool HasExplicitlyImplementedProperty(this Type type, Type interfa
426298 return hasGetter || hasSetter ;
427299 }
428300
301+ private static bool HasParameterlessMethod ( this Type type , string methodName )
302+ {
303+ return type . GetParameterlessMethod ( methodName ) is not null ;
304+ }
305+
429306 public static PropertyInfo GetIndexerByParameterTypes ( this Type type , IEnumerable < Type > parameterTypes )
430307 {
431308 return type . GetProperties ( AllStaticAndInstanceMembersFlag )
0 commit comments