1+ using System . Collections . Concurrent ;
2+ using System . Collections . Generic ;
3+ using System . Reflection ;
4+ using System . Xml ;
5+ using System . Xml . Linq ;
6+
7+ namespace System . Linq . Dynamic . Core . Parser ;
8+
9+ internal static class EnumerationsAndWellKnownTypesFromMscorlib
10+ {
11+ private readonly static string SystemPrivateCoreLib = typeof ( StringComparer ) . GetTypeInfo ( ) . Assembly . FullName ! ;
12+ private readonly static string SystemPrivateUri = typeof ( UriFormat ) . GetTypeInfo ( ) . Assembly . FullName ! ;
13+ private readonly static string SystemPrivateXml = typeof ( XmlNodeType ) . GetTypeInfo ( ) . Assembly . FullName ! ;
14+ private readonly static string SystemPrivateXmlLinq = typeof ( XObject ) . GetTypeInfo ( ) . Assembly . FullName ! ;
15+
16+ /// <summary>
17+ /// Enum types and well-known types.
18+ /// </summary>
19+ public static readonly ConcurrentDictionary < string , Type > PredefinedEnumerationTypes = new ( StringComparer . OrdinalIgnoreCase ) ;
20+
21+ static EnumerationsAndWellKnownTypesFromMscorlib ( )
22+ {
23+ var list = AddEnumsAndWellKnownTypesFromAssembly ( SystemPrivateUri ) ;
24+ list . AddRange ( AddEnumsAndWellKnownTypesFromAssembly ( SystemPrivateCoreLib ) ) ;
25+ list . AddRange ( AddEnumsAndWellKnownTypesFromAssembly ( SystemPrivateXml ) ) ;
26+ list . AddRange ( AddEnumsAndWellKnownTypesFromAssembly ( SystemPrivateXmlLinq ) ) ;
27+
28+ #if ! ( NET35 || NETSTANDARD1_3 )
29+ var systemPrivateDataContractSerialization = typeof ( Runtime . Serialization . DataContractResolver ) . GetTypeInfo ( ) . Assembly . FullName ! ;
30+ list . AddRange ( AddEnumsAndWellKnownTypesFromAssembly ( systemPrivateDataContractSerialization ) ) ;
31+ #endif
32+ foreach ( var group in list . GroupBy ( t => t . Name ) )
33+ {
34+ Add ( group ) ;
35+ }
36+ }
37+
38+ private static List < Type > AddEnumsAndWellKnownTypesFromAssembly ( string assemblyName )
39+ {
40+ try
41+ {
42+ var assembly = Assembly . Load ( new AssemblyName ( assemblyName ) ) ;
43+ var types = assembly . GetTypes ( ) . ToArray ( ) ;
44+
45+ var enumTypes = types . Where ( t => t . GetTypeInfo ( ) . IsEnum && t . GetTypeInfo ( ) . IsPublic ) ;
46+ var enumLikeTypes = FindEnumLikeTypes ( types . Where ( x => x == typeof ( StringComparer ) ) . ToArray ( ) ) ;
47+
48+ return enumTypes . Union ( enumLikeTypes ) . ToList ( ) ;
49+ }
50+ catch
51+ {
52+ return [ ] ;
53+ }
54+ }
55+
56+ private static Type [ ] FindEnumLikeTypes ( Type [ ] types )
57+ {
58+ try
59+ {
60+ return types
61+ . Where ( t => t . GetTypeInfo ( ) . IsPublic && ! t . GetTypeInfo ( ) . IsEnum && HasStaticPropertiesOrFieldsOfOwnType ( t ) )
62+ . ToArray ( ) ;
63+ }
64+ catch
65+ {
66+ return [ ] ;
67+ }
68+ }
69+
70+ private static bool HasStaticPropertiesOrFieldsOfOwnType ( Type type )
71+ {
72+ var baseType = type . GetTypeInfo ( ) . BaseType ;
73+
74+ var anyStaticProperties = type . GetProperties ( BindingFlags . Public | BindingFlags . Static )
75+ . Any ( p => p . PropertyType == type || p . PropertyType == baseType ) ;
76+
77+ if ( anyStaticProperties )
78+ {
79+ return true ;
80+ }
81+
82+ var anyStaticFields = type . GetFields ( BindingFlags . Public | BindingFlags . Static )
83+ . Any ( f => f . FieldType == type || f . FieldType == baseType ) ;
84+
85+ return anyStaticFields ;
86+ }
87+
88+ private static void Add ( IGrouping < string , Type > group )
89+ {
90+ if ( group . Count ( ) == 1 )
91+ {
92+ var singleType = group . Single ( ) ;
93+ PredefinedEnumerationTypes . TryAdd ( group . Key , singleType ) ;
94+ PredefinedEnumerationTypes . TryAdd ( singleType . FullName ! , singleType ) ;
95+ }
96+ else
97+ {
98+ foreach ( var fullType in group )
99+ {
100+ PredefinedEnumerationTypes . TryAdd ( fullType . FullName ! , fullType ) ;
101+ }
102+ }
103+ }
104+ }
0 commit comments