44 using System . Collections . Generic ;
55 using System . Linq ;
66 using System . Reflection ;
7+ #if ! NET_STANDARD
8+ using static System . Reflection . BindingFlags ;
9+ #endif
710
811 /// <summary>
912 /// Provides a set of static methods for obtaining field information in .NET Standard 1.0 and .NET 4.0.
@@ -18,9 +21,9 @@ public static class FieldExtensionsPolyfill
1821 public static IEnumerable < FieldInfo > GetPublicStaticFields ( this Type type )
1922 {
2023#if NET_STANDARD
21- return type . GetTypeInfo ( ) . DeclaredFields . Where ( f => f . IsPublic && f . IsStatic ) ;
24+ return GetFields ( type , isPublic : true , isStatic : true ) ;
2225#else
23- return type . GetFields ( BindingFlags . Public | BindingFlags . Static ) ;
26+ return GetFields ( type , Public | Static ) ;
2427#endif
2528 }
2629
@@ -36,9 +39,9 @@ public static IEnumerable<FieldInfo> GetPublicStaticFields(this Type type)
3639 public static FieldInfo GetPublicStaticField ( this Type type , string name )
3740 {
3841#if NET_STANDARD
39- return type . GetPublicStaticFields ( ) . FirstOrDefault ( f => f . Name == name ) ;
42+ return GetFields ( type , name , isPublic : true , isStatic : true ) . FirstOrDefault ( ) ;
4043#else
41- return type . GetField ( name , BindingFlags . Public | BindingFlags . Static ) ;
44+ return GetFields ( type , name , Public | Static ) . FirstOrDefault ( ) ;
4245#endif
4346 }
4447
@@ -50,9 +53,9 @@ public static FieldInfo GetPublicStaticField(this Type type, string name)
5053 public static IEnumerable < FieldInfo > GetPublicInstanceFields ( this Type type )
5154 {
5255#if NET_STANDARD
53- return type . GetTypeInfo ( ) . DeclaredFields . Where ( f => f . IsPublic && ! f . IsStatic ) ;
56+ return GetFields ( type , isPublic : true , isStatic : false ) ;
5457#else
55- return type . GetFields ( BindingFlags . Public | BindingFlags . Instance ) ;
58+ return GetFields ( type , Public | Instance ) ;
5659#endif
5760 }
5861
@@ -68,9 +71,9 @@ public static IEnumerable<FieldInfo> GetPublicInstanceFields(this Type type)
6871 public static FieldInfo GetPublicInstanceField ( this Type type , string name )
6972 {
7073#if NET_STANDARD
71- return type . GetPublicInstanceFields ( ) . FirstOrDefault ( f => f . Name == name ) ;
74+ return GetFields ( type , name , isPublic : true , isStatic : false ) . FirstOrDefault ( ) ;
7275#else
73- return type . GetField ( name , BindingFlags . Public | BindingFlags . Instance ) ;
76+ return GetFields ( type , name , Public | Instance ) . FirstOrDefault ( ) ;
7477#endif
7578 }
7679
@@ -82,15 +85,9 @@ public static FieldInfo GetPublicInstanceField(this Type type, string name)
8285 public static IEnumerable < FieldInfo > GetNonPublicStaticFields ( this Type type )
8386 {
8487#if NET_STANDARD
85- return type
86- . GetTypeInfo ( )
87- . DeclaredFields
88- . Where ( f => ! f . IsPublic && f . IsStatic )
89- . WithoutAutoGeneratedBackingFields ( ) ;
88+ return GetFields ( type , isPublic : false , isStatic : true ) ;
9089#else
91- return type
92- . GetFields ( BindingFlags . NonPublic | BindingFlags . Static )
93- . WithoutAutoGeneratedBackingFields ( ) ;
90+ return GetFields ( type , NonPublic | Static ) ;
9491#endif
9592 }
9693
@@ -106,9 +103,9 @@ public static IEnumerable<FieldInfo> GetNonPublicStaticFields(this Type type)
106103 public static FieldInfo GetNonPublicStaticField ( this Type type , string name )
107104 {
108105#if NET_STANDARD
109- return type . GetNonPublicStaticFields ( ) . FirstOrDefault ( f => f . Name == name ) ;
106+ return GetFields ( type , name , isPublic : false , isStatic : true ) . FirstOrDefault ( ) ;
110107#else
111- return type . GetField ( name , BindingFlags . NonPublic | BindingFlags . Static ) ;
108+ return GetFields ( type , name , NonPublic | Static ) . FirstOrDefault ( ) ;
112109#endif
113110 }
114111
@@ -120,15 +117,9 @@ public static FieldInfo GetNonPublicStaticField(this Type type, string name)
120117 public static IEnumerable < FieldInfo > GetNonPublicInstanceFields ( this Type type )
121118 {
122119#if NET_STANDARD
123- return type
124- . GetTypeInfo ( )
125- . DeclaredFields
126- . Where ( f => ! f . IsPublic && ! f . IsStatic )
127- . WithoutAutoGeneratedBackingFields ( ) ;
120+ return GetFields ( type , isPublic : false , isStatic : false ) ;
128121#else
129- return type
130- . GetFields ( BindingFlags . NonPublic | BindingFlags . Instance )
131- . WithoutAutoGeneratedBackingFields ( ) ;
122+ return GetFields ( type , NonPublic | Instance ) ;
132123#endif
133124 }
134125
@@ -144,15 +135,57 @@ public static IEnumerable<FieldInfo> GetNonPublicInstanceFields(this Type type)
144135 public static FieldInfo GetNonPublicInstanceField ( this Type type , string name )
145136 {
146137#if NET_STANDARD
147- return type . GetNonPublicInstanceFields ( ) . FirstOrDefault ( f => f . Name == name ) ;
138+ return GetFields ( type , name , isPublic : false , isStatic : false ) . FirstOrDefault ( ) ;
148139#else
149- return type . GetField ( name , BindingFlags . NonPublic | BindingFlags . Instance ) ;
140+ return GetFields ( type , name , NonPublic | Instance ) . FirstOrDefault ( ) ;
150141#endif
151142 }
152143
153- private static IEnumerable < FieldInfo > WithoutAutoGeneratedBackingFields ( this IEnumerable < FieldInfo > fields )
144+ #region Helper Methods
145+
146+ #if NET_STANDARD
147+ internal static IEnumerable < FieldInfo > GetFields ( this Type type , bool isPublic , bool isStatic )
148+ => GetFields ( type , name : null , isPublic : isPublic , isStatic : isStatic ) ;
149+
150+ private static IEnumerable < FieldInfo > GetFields ( Type type , string name , bool isPublic , bool isStatic )
154151 {
155- return fields . Where ( f => f . Name [ 0 ] != '<' ) ;
152+ return GetFields (
153+ type ,
154+ t => t . GetTypeInfo ( ) . DeclaredFields ,
155+ name ,
156+ f => ( f . IsPublic == isPublic ) && ( f . IsStatic == isStatic ) ) ;
156157 }
158+ #else
159+ private static IEnumerable < FieldInfo > GetFields ( Type type , BindingFlags bindingFlags )
160+ => GetFields ( type , name : null , bindingFlags : bindingFlags ) ;
161+
162+ private static IEnumerable < FieldInfo > GetFields ( Type type , string name , BindingFlags bindingFlags )
163+ => GetFields ( type , t => t . GetFields ( bindingFlags ) , name ) ;
164+ #endif
165+ private static IEnumerable < FieldInfo > GetFields (
166+ Type type ,
167+ Func < Type , IEnumerable < FieldInfo > > fieldsFactory ,
168+ string name ,
169+ Func < FieldInfo , bool > fieldFilter = null )
170+ {
171+ if ( fieldFilter == null )
172+ {
173+ fieldFilter = f => true ;
174+ }
175+
176+ return MemberFinder < FieldInfo > . EnumerateMembers (
177+ type ,
178+ fieldsFactory ,
179+ name ,
180+ f => IsNotAutoGeneratedBackingField ( f ) && fieldFilter . Invoke ( f ) ,
181+ FieldNotAlreadyIncluded ) ;
182+ }
183+
184+ private static bool IsNotAutoGeneratedBackingField ( this MemberInfo field ) => field . Name [ 0 ] != '<' ;
185+
186+ private static bool FieldNotAlreadyIncluded ( FieldInfo field , ICollection < FieldInfo > fieldsSoFar )
187+ => ( fieldsSoFar . Count == 0 ) || fieldsSoFar . All ( f => f . Name != field . Name ) ;
188+
189+ #endregion
157190 }
158191}
0 commit comments