1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Text ;
5+ using System . Collections ;
6+ using System . Dynamic ;
7+ using System . Linq . Expressions ;
8+
9+ namespace Simple . Data
10+ {
11+ internal static class ConcreteCollectionTypeCreator
12+ {
13+ private static readonly List < Creator > _creators = new List < Creator >
14+ {
15+ new GenericSetCreator ( ) ,
16+ new GenericListCreator ( ) ,
17+ new NonGenericListCreator ( )
18+ } ;
19+
20+ public static bool IsCollectionType ( Type type )
21+ {
22+ return _creators . Any ( c => c . IsCollectionType ( type ) ) ;
23+ }
24+
25+ public static bool TryCreate ( Type type , IEnumerable items , out object result )
26+ {
27+ return _creators . First ( c => c . IsCollectionType ( type ) ) . TryCreate ( type , items , out result ) ;
28+ }
29+
30+ private abstract class Creator
31+ {
32+ public abstract bool IsCollectionType ( Type type ) ;
33+
34+ public abstract bool TryCreate ( Type type , IEnumerable items , out object result ) ;
35+
36+ protected bool TryConvertElement ( Type type , object value , out object result )
37+ {
38+ result = null ;
39+ if ( value == null )
40+ return true ;
41+
42+ var valueType = value . GetType ( ) ;
43+
44+ if ( type . IsAssignableFrom ( valueType ) )
45+ {
46+ result = value ;
47+ return true ;
48+ }
49+
50+ try
51+ {
52+ var code = System . Convert . GetTypeCode ( value ) ;
53+
54+ if ( type . IsEnum )
55+ {
56+ if ( value is string )
57+ {
58+ result = Enum . Parse ( type , ( string ) value ) ;
59+ return true ;
60+ }
61+ else
62+ {
63+ result = Enum . ToObject ( type , value ) ;
64+ return true ;
65+ }
66+ }
67+ else if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) )
68+ {
69+ result = System . Convert . ChangeType ( value , Nullable . GetUnderlyingType ( type ) ) ;
70+ return true ;
71+ }
72+ else if ( code != TypeCode . Object )
73+ {
74+ result = System . Convert . ChangeType ( value , type ) ;
75+ return true ;
76+ }
77+ else
78+ {
79+ var data = value as IDictionary < string , object > ;
80+ if ( data != null )
81+ return ConcreteTypeCreator . Get ( type ) . TryCreate ( data , out result ) ;
82+ }
83+ }
84+ catch ( FormatException )
85+ {
86+ return false ;
87+ }
88+ catch ( ArgumentException )
89+ {
90+ return false ;
91+ }
92+
93+ return true ;
94+ }
95+
96+ protected bool TryConvertElements ( Type type , IEnumerable items , out Array result )
97+ {
98+ result = null ;
99+ List < object > list ;
100+ if ( items == null )
101+ list = new List < object > ( ) ;
102+ else
103+ list = items . OfType < object > ( ) . ToList ( ) ;
104+
105+ var array = Array . CreateInstance ( type , list . Count ) ;
106+ object element ;
107+ for ( var i = 0 ; i < array . Length ; i ++ )
108+ {
109+ if ( ! TryConvertElement ( type , list [ i ] , out element ) )
110+ return false ;
111+ array . SetValue ( element , i ) ;
112+ }
113+
114+ result = array ;
115+ return true ;
116+ }
117+ }
118+
119+ private class NonGenericListCreator : Creator
120+ {
121+ public override bool IsCollectionType ( Type type )
122+ {
123+ if ( type == typeof ( string ) )
124+ return false ;
125+
126+ return type == typeof ( IEnumerable ) ||
127+ type == typeof ( ICollection ) ||
128+ type == typeof ( IList ) ||
129+ type == typeof ( ArrayList ) ;
130+ }
131+
132+ public override bool TryCreate ( Type type , IEnumerable items , out object result )
133+ {
134+ var list = new ArrayList ( items . OfType < object > ( ) . ToList ( ) ) ;
135+ result = list ;
136+ return true ;
137+ }
138+ }
139+
140+ private class GenericListCreator : Creator
141+ {
142+ private static readonly Type _openListType = typeof ( List < > ) ;
143+
144+ public override bool IsCollectionType ( Type type )
145+ {
146+ if ( ! type . IsGenericType )
147+ return false ;
148+
149+ var genericTypeDef = type . GetGenericTypeDefinition ( ) ;
150+ if ( genericTypeDef . GetGenericArguments ( ) . Length != 1 )
151+ return false ;
152+
153+ return genericTypeDef == typeof ( IEnumerable < > ) ||
154+ genericTypeDef == typeof ( ICollection < > ) ||
155+ genericTypeDef == typeof ( IList < > ) ||
156+ genericTypeDef == typeof ( List < > ) ;
157+ }
158+
159+ public override bool TryCreate ( Type type , IEnumerable items , out object result )
160+ {
161+ result = null ;
162+ var elementType = GetElementType ( type ) ;
163+ var listType = _openListType . MakeGenericType ( elementType ) ;
164+ Array elements ;
165+ if ( ! TryConvertElements ( elementType , items , out elements ) )
166+ return false ;
167+
168+ result = Activator . CreateInstance ( listType , elements ) ;
169+ return true ;
170+ }
171+
172+ private Type GetElementType ( Type type )
173+ {
174+ return type . GetGenericArguments ( ) [ 0 ] ;
175+ }
176+ }
177+
178+ private class GenericSetCreator : Creator
179+ {
180+ private static readonly Type _openSetType = typeof ( HashSet < > ) ;
181+
182+ public override bool IsCollectionType ( Type type )
183+ {
184+ if ( ! type . IsGenericType )
185+ return false ;
186+
187+ var genericTypeDef = type . GetGenericTypeDefinition ( ) ;
188+ if ( genericTypeDef . GetGenericArguments ( ) . Length != 1 )
189+ return false ;
190+
191+ return genericTypeDef == typeof ( ISet < > ) ||
192+ genericTypeDef == typeof ( HashSet < > ) ;
193+ }
194+
195+ public override bool TryCreate ( Type type , IEnumerable items , out object result )
196+ {
197+ result = null ;
198+ var elementType = GetElementType ( type ) ;
199+ var setType = _openSetType . MakeGenericType ( elementType ) ;
200+ Array elements ;
201+ if ( ! TryConvertElements ( elementType , items , out elements ) )
202+ return false ;
203+
204+ result = Activator . CreateInstance ( setType , elements ) ;
205+ return true ;
206+ }
207+
208+ private Type GetElementType ( Type type )
209+ {
210+ return type . GetGenericArguments ( ) [ 0 ] ;
211+ }
212+ }
213+ }
214+ }
0 commit comments