Code Coverage Statistics for Source File
Newtonsoft.Json\Utilities\CollectionUtils.cs
Symbol Coverage: 42.86% (123 of 287)
Branch Coverage: 37.06% (63 of 170)
Cyclomatic Complexity Avg: 3.05 Max:17
Code Lines: 267
Symbol Coverage Trend
View:
L | V | Source |
---|---|---|
1 |
#region License |
|
2 |
// Copyright (c) 2007 James Newton-King |
|
3 |
// |
|
4 |
// Permission is hereby granted, free of charge, to any person |
|
5 |
// obtaining a copy of this software and associated documentation |
|
6 |
// files (the "Software"), to deal in the Software without |
|
7 |
// restriction, including without limitation the rights to use, |
|
8 |
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
9 |
// copies of the Software, and to permit persons to whom the |
|
10 |
// Software is furnished to do so, subject to the following |
|
11 |
// conditions: |
|
12 |
// |
|
13 |
// The above copyright notice and this permission notice shall be |
|
14 |
// included in all copies or substantial portions of the Software. |
|
15 |
// |
|
16 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
17 |
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|
18 |
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
19 |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
20 |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
21 |
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
22 |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
23 |
// OTHER DEALINGS IN THE SOFTWARE. |
|
24 |
#endregion |
|
25 |
||
26 |
using System; |
|
27 |
using System.Collections.Generic; |
|
28 |
using System.Collections.ObjectModel; |
|
29 |
using System.Reflection; |
|
30 |
using System.Text; |
|
31 |
using System.Collections; |
|
32 |
using System.Linq; |
|
33 |
using System.Globalization; |
|
34 |
||
35 |
namespace Newtonsoft.Json.Utilities |
|
36 |
{ |
|
37 |
internal static class CollectionUtils |
|
38 |
{ |
|
39 |
public static IEnumerable<T> CastValid<T>(this IEnumerable enumerable) |
|
40 |
{ |
|
41 |
0 |
ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
|
42 |
||
43 |
0 |
return enumerable.Cast<object>().Where(o => o is T).Cast<T>();
|
44 |
0 |
}
|
45 |
||
46 |
public static List<T> CreateList<T>(params T[] values) |
|
47 |
{ |
|
48 |
0 |
return new List<T>(values);
|
49 |
0 |
}
|
50 |
||
51 |
/// <summary> |
|
52 |
/// Determines whether the collection is null or empty. |
|
53 |
/// </summary> |
|
54 |
/// <param name="collection">The collection.</param> |
|
55 |
/// <returns> |
|
56 |
/// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>. |
|
57 |
/// </returns> |
|
58 |
public static bool IsNullOrEmpty(ICollection collection) |
|
59 |
{ |
|
60 |
0 |
if (collection != null)
|
61 |
{ |
|
62 |
0 |
return (collection.Count == 0);
|
63 |
} |
|
64 |
0 |
return true;
|
65 |
0 |
}
|
66 |
||
67 |
/// <summary> |
|
68 |
/// Determines whether the collection is null or empty. |
|
69 |
/// </summary> |
|
70 |
/// <param name="collection">The collection.</param> |
|
71 |
/// <returns> |
|
72 |
/// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>. |
|
73 |
/// </returns> |
|
74 |
public static bool IsNullOrEmpty<T>(ICollection<T> collection) |
|
75 |
{ |
|
76 |
414 |
if (collection != null)
|
77 |
{ |
|
78 |
254 |
return (collection.Count == 0);
|
79 |
} |
|
80 |
160 |
return true;
|
81 |
414 |
}
|
82 |
||
83 |
/// <summary> |
|
84 |
/// Determines whether the collection is null, empty or its contents are uninitialized values. |
|
85 |
/// </summary> |
|
86 |
/// <param name="list">The list.</param> |
|
87 |
/// <returns> |
|
88 |
/// <c>true</c> if the collection is null or empty or its contents are uninitialized values; otherwise, <c>false</c>. |
|
89 |
/// </returns> |
|
90 |
public static bool IsNullOrEmptyOrDefault<T>(IList<T> list) |
|
91 |
{ |
|
92 |
0 |
if (IsNullOrEmpty<T>(list))
|
93 |
0 |
return true;
|
94 |
||
95 |
0 |
return ReflectionUtils.ItemsUnitializedValue<T>(list);
|
96 |
0 |
}
|
97 |
||
98 |
/// <summary> |
|
99 |
/// Makes a slice of the specified list in between the start and end indexes. |
|
100 |
/// </summary> |
|
101 |
/// <param name="list">The list.</param> |
|
102 |
/// <param name="start">The start index.</param> |
|
103 |
/// <param name="end">The end index.</param> |
|
104 |
/// <returns>A slice of the list.</returns> |
|
105 |
public static IList<T> Slice<T>(IList<T> list, int? start, int? end) |
|
106 |
{ |
|
107 |
0 |
return Slice<T>(list, start, end, null);
|
108 |
0 |
}
|
109 |
||
110 |
/// <summary> |
|
111 |
/// Makes a slice of the specified list in between the start and end indexes, |
|
112 |
/// getting every so many items based upon the step. |
|
113 |
/// </summary> |
|
114 |
/// <param name="list">The list.</param> |
|
115 |
/// <param name="start">The start index.</param> |
|
116 |
/// <param name="end">The end index.</param> |
|
117 |
/// <param name="step">The step.</param> |
|
118 |
/// <returns>A slice of the list.</returns> |
|
119 |
public static IList<T> Slice<T>(IList<T> list, int? start, int? end, int? step) |
|
120 |
{ |
|
121 |
0 |
if (list == null)
|
122 |
0 |
throw new ArgumentNullException("list");
|
123 |
||
124 |
0 |
if (step == 0)
|
125 |
0 |
throw new ArgumentException("Step cannot be zero.", "step");
|
126 |
||
127 |
0 |
List<T> slicedList = new List<T>();
|
128 |
||
129 |
// nothing to slice |
|
130 |
0 |
if (list.Count == 0)
|
131 |
0 |
return slicedList;
|
132 |
||
133 |
// set defaults for null arguments |
|
134 |
0 |
int s = step ?? 1;
|
135 |
0 |
int startIndex = start ?? 0;
|
136 |
0 |
int endIndex = end ?? list.Count;
|
137 |
||
138 |
// start from the end of the list if start is negitive |
|
139 |
0 |
startIndex = (startIndex < 0) ? list.Count + startIndex : startIndex;
|
140 |
||
141 |
// end from the start of the list if end is negitive |
|
142 |
0 |
endIndex = (endIndex < 0) ? list.Count + endIndex : endIndex;
|
143 |
||
144 |
// ensure indexes keep within collection bounds |
|
145 |
0 |
startIndex = Math.Max(startIndex, 0);
|
146 |
0 |
endIndex = Math.Min(endIndex, list.Count - 1);
|
147 |
||
148 |
// loop between start and end indexes, incrementing by the step |
|
149 |
0 |
for (int i = startIndex; i < endIndex; i += s) |
150 |
{ |
|
151 |
0 |
slicedList.Add(list[i]);
|
152 |
} |
|
153 |
||
154 |
0 |
return slicedList;
|
155 |
0 |
}
|
156 |
||
157 |
||
158 |
/// <summary> |
|
159 |
/// Group the collection using a function which returns the key. |
|
160 |
/// </summary> |
|
161 |
/// <param name="source">The source collection to group.</param> |
|
162 |
/// <param name="keySelector">The key selector.</param> |
|
163 |
/// <returns>A Dictionary with each key relating to a list of objects in a list grouped under it.</returns> |
|
164 |
public static Dictionary<K, List<V>> GroupBy<K, V>(ICollection<V> source, Func<V, K> keySelector) |
|
165 |
{ |
|
166 |
0 |
if (keySelector == null)
|
167 |
0 |
throw new ArgumentNullException("keySelector");
|
168 |
||
169 |
0 |
Dictionary<K, List<V>> groupedValues = new Dictionary<K, List<V>>();
|
170 |
||
171 |
0 |
foreach (V value in source)
|
172 |
{ |
|
173 |
// using delegate to get the value's key |
|
174 |
0 |
K key = keySelector(value);
|
175 |
List<V> groupedValueList; |
|
176 |
||
177 |
// add a list for grouped values if the key is not already in Dictionary |
|
178 |
0 |
if (!groupedValues.TryGetValue(key, out groupedValueList))
|
179 |
{ |
|
180 |
0 |
groupedValueList = new List<V>();
|
181 |
0 |
groupedValues.Add(key, groupedValueList);
|
182 |
} |
|
183 |
||
184 |
0 |
groupedValueList.Add(value);
|
185 |
} |
|
186 |
||
187 |
0 |
return groupedValues;
|
188 |
0 |
}
|
189 |
||
190 |
/// <summary> |
|
191 |
/// Adds the elements of the specified collection to the specified generic IList. |
|
192 |
/// </summary> |
|
193 |
/// <param name="initial">The list to add to.</param> |
|
194 |
/// <param name="collection">The collection of elements to add.</param> |
|
195 |
public static void AddRange<T>(this IList<T> initial, IEnumerable<T> collection) |
|
196 |
{ |
|
197 |
1187 |
if (initial == null)
|
198 |
0 |
throw new ArgumentNullException("initial");
|
199 |
||
200 |
1187 |
if (collection == null)
|
201 |
0 |
return;
|
202 |
||
203 |
1187 |
foreach (T value in collection)
|
204 |
{ |
|
205 |
2481 |
initial.Add(value);
|
206 |
} |
|
207 |
1187 |
}
|
208 |
||
209 |
public static void AddRange(this IList initial, IEnumerable collection) |
|
210 |
{ |
|
211 |
693 |
ValidationUtils.ArgumentNotNull(initial, "initial");
|
212 |
||
213 |
693 |
ListWrapper<object> wrapper = new ListWrapper<object>(initial);
|
214 |
693 |
wrapper.AddRange(collection.Cast<object>());
|
215 |
693 |
}
|
216 |
||
217 |
public static List<T> Distinct<T>(List<T> collection) |
|
218 |
{ |
|
219 |
0 |
List<T> distinctList = new List<T>();
|
220 |
||
221 |
0 |
foreach (T value in collection)
|
222 |
{ |
|
223 |
0 |
if (!distinctList.Contains(value))
|
224 |
0 |
distinctList.Add(value);
|
225 |
} |
|
226 |
||
227 |
0 |
return distinctList;
|
228 |
0 |
}
|
229 |
||
230 |
public static List<List<T>> Flatten<T>(params IList<T>[] lists) |
|
231 |
{ |
|
232 |
0 |
List<List<T>> flattened = new List<List<T>>();
|
233 |
0 |
Dictionary<int, T> currentList = new Dictionary<int, T>();
|
234 |
||
235 |
0 |
Recurse<T>(new List<IList<T>>(lists), 0, currentList, flattened);
|
236 |
||
237 |
0 |
return flattened;
|
238 |
0 |
}
|
239 |
||
240 |
private static void Recurse<T>(IList<IList<T>> global, int current, Dictionary<int, T> currentSet, List<List<T>> flattenedResult) |
|
241 |
{ |
|
242 |
0 |
IList<T> currentArray = global[current];
|
243 |
||
244 |
0 |
for (int i = 0; i < currentArray.Count; i++) |
245 |
{ |
|
246 |
0 |
currentSet[current] = currentArray[i];
|
247 |
||
248 |
0 |
if (current == global.Count - 1)
|
249 |
{ |
|
250 |
0 |
List<T> items = new List<T>();
|
251 |
||
252 |
0 |
for (int k = 0; k < currentSet.Count; k++) |
253 |
{ |
|
254 |
0 |
items.Add(currentSet[k]);
|
255 |
} |
|
256 |
||
257 |
0 |
flattenedResult.Add(items);
|
258 |
} |
|
259 |
else |
|
260 |
{ |
|
261 |
0 |
Recurse(global, current + 1, currentSet, flattenedResult);
|
262 |
} |
|
263 |
} |
|
264 |
0 |
}
|
265 |
||
266 |
public static List<T> CreateList<T>(ICollection collection) |
|
267 |
{ |
|
268 |
0 |
if (collection == null)
|
269 |
0 |
throw new ArgumentNullException("collection");
|
270 |
||
271 |
0 |
T[] array = new T[collection.Count];
|
272 |
0 |
collection.CopyTo(array, 0);
|
273 |
||
274 |
0 |
return new List<T>(array);
|
275 |
0 |
}
|
276 |
||
277 |
public static bool ListEquals<T>(IList<T> a, IList<T> b) |
|
278 |
{ |
|
279 |
0 |
if (a == null || b == null)
|
280 |
0 |
return (a == null && b == null);
|
281 |
||
282 |
0 |
if (a.Count != b.Count)
|
283 |
0 |
return false;
|
284 |
||
285 |
0 |
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
286 |
||
287 |
0 |
for (int i = 0; i < a.Count; i++) |
288 |
{ |
|
289 |
0 |
if (!comparer.Equals(a[i], b[i]))
|
290 |
0 |
return false;
|
291 |
} |
|
292 |
||
293 |
0 |
return true;
|
294 |
0 |
}
|
295 |
||
296 |
#region GetSingleItem |
|
297 |
public static bool TryGetSingleItem<T>(IList<T> list, out T value) |
|
298 |
{ |
|
299 |
0 |
return TryGetSingleItem<T>(list, false, out value);
|
300 |
0 |
}
|
301 |
||
302 |
public static bool TryGetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty, out T value) |
|
303 |
{ |
|
304 |
0 |
return MiscellaneousUtils.TryAction<T>(delegate { return GetSingleItem(list, returnDefaultIfEmpty); }, out value);
|
305 |
0 |
}
|
306 |
||
307 |
public static T GetSingleItem<T>(IList<T> list) |
|
308 |
{ |
|
309 |
0 |
return GetSingleItem<T>(list, false);
|
310 |
0 |
}
|
311 |
||
312 |
public static T GetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty) |
|
313 |
{ |
|
314 |
4218 |
if (list.Count == 1)
|
315 |
185 |
return list[0];
|
316 |
4033 |
else if (returnDefaultIfEmpty && list.Count == 0)
|
317 |
4033 |
return default(T);
|
318 |
else |
|
319 |
0 |
throw new Exception("Expected single {0} in list but got {1}.".FormatWith(CultureInfo.InvariantCulture, typeof(T), list.Count));
|
320 |
4218 |
}
|
321 |
#endregion |
|
322 |
||
323 |
public static IList<T> Minus<T>(IList<T> list, IList<T> minus) |
|
324 |
{ |
|
325 |
0 |
ValidationUtils.ArgumentNotNull(list, "list");
|
326 |
||
327 |
0 |
List<T> result = new List<T>(list.Count);
|
328 |
0 |
foreach (T t in list)
|
329 |
{ |
|
330 |
0 |
if (minus == null || !minus.Contains(t))
|
331 |
0 |
result.Add(t);
|
332 |
} |
|
333 |
||
334 |
0 |
return result;
|
335 |
0 |
}
|
336 |
||
337 |
public static IList CreateGenericList(Type listType) |
|
338 |
{ |
|
339 |
1 |
ValidationUtils.ArgumentNotNull(listType, "listType");
|
340 |
||
341 |
1 |
return (IList)ReflectionUtils.CreateGeneric(typeof(List<>), listType);
|
342 |
1 |
}
|
343 |
||
344 |
public static IDictionary CreateGenericDictionary(Type keyType, Type valueType) |
|
345 |
{ |
|
346 |
0 |
ValidationUtils.ArgumentNotNull(keyType, "keyType");
|
347 |
0 |
ValidationUtils.ArgumentNotNull(valueType, "valueType");
|
348 |
||
349 |
0 |
return (IDictionary)ReflectionUtils.CreateGeneric(typeof(Dictionary<,>), keyType, valueType);
|
350 |
0 |
}
|
351 |
||
352 |
public static bool IsListType(Type type) |
|
353 |
{ |
|
354 |
0 |
ValidationUtils.ArgumentNotNull(type, "type");
|
355 |
||
356 |
0 |
if (type.IsArray)
|
357 |
0 |
return true;
|
358 |
0 |
if (typeof(IList).IsAssignableFrom(type))
|
359 |
0 |
return true;
|
360 |
0 |
if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IList<>)))
|
361 |
0 |
return true;
|
362 |
||
363 |
0 |
return false;
|
364 |
0 |
}
|
365 |
||
366 |
public static bool IsCollectionType(Type type) |
|
367 |
{ |
|
368 |
0 |
ValidationUtils.ArgumentNotNull(type, "type");
|
369 |
||
370 |
0 |
if (type.IsArray)
|
371 |
0 |
return true;
|
372 |
0 |
if (typeof(ICollection).IsAssignableFrom(type))
|
373 |
0 |
return true;
|
374 |
0 |
if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(ICollection<>)))
|
375 |
0 |
return true;
|
376 |
||
377 |
0 |
return false;
|
378 |
0 |
}
|
379 |
||
380 |
public static bool IsDictionaryType(Type type) |
|
381 |
{ |
|
382 |
248 |
ValidationUtils.ArgumentNotNull(type, "type");
|
383 |
||
384 |
248 |
if (typeof(IDictionary).IsAssignableFrom(type))
|
385 |
14 |
return true;
|
386 |
234 |
if (ReflectionUtils.ImplementsGenericDefinition(type, typeof (IDictionary<,>)))
|
387 |
2 |
return true;
|
388 |
||
389 |
232 |
return false;
|
390 |
248 |
}
|
391 |
||
392 |
public static IWrappedCollection CreateCollectionWrapper(object list) |
|
393 |
{ |
|
394 |
2 |
ValidationUtils.ArgumentNotNull(list, "list");
|
395 |
||
396 |
Type collectionDefinition; |
|
397 |
2 |
if (ReflectionUtils.ImplementsGenericDefinition(list.GetType(), typeof(ICollection<>), out collectionDefinition))
|
398 |
{ |
|
399 |
2 |
Type collectionItemType = ReflectionUtils.GetCollectionItemType(collectionDefinition);
|
400 |
||
401 |
// Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor |
|
402 |
2 |
Func<Type, IList<object>, object> instanceCreator = (t, a) =>
|
403 |
2 |
{
|
404 |
2 |
ConstructorInfo c = t.GetConstructor(new[] { collectionDefinition });
|
405 |
2 |
return c.Invoke(new[] { list });
|
406 |
2 |
};
|
407 |
||
408 |
2 |
return (IWrappedCollection)ReflectionUtils.CreateGeneric(typeof(CollectionWrapper<>), new[] { collectionItemType }, instanceCreator, list);
|
409 |
} |
|
410 |
0 |
else if (list is IList)
|
411 |
{ |
|
412 |
0 |
return new CollectionWrapper<object>((IList)list);
|
413 |
} |
|
414 |
else |
|
415 |
{ |
|
416 |
0 |
throw new Exception("Can not create ListWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, list.GetType()));
|
417 |
} |
|
418 |
2 |
}
|
419 |
public static IWrappedList CreateListWrapper(object list) |
|
420 |
{ |
|
421 |
0 |
ValidationUtils.ArgumentNotNull(list, "list");
|
422 |
||
423 |
Type listDefinition; |
|
424 |
0 |
if (ReflectionUtils.ImplementsGenericDefinition(list.GetType(), typeof(IList<>), out listDefinition))
|
425 |
{ |
|
426 |
0 |
Type collectionItemType = ReflectionUtils.GetCollectionItemType(listDefinition);
|
427 |
||
428 |
// Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor |
|
429 |
0 |
Func<Type, IList<object>, object> instanceCreator = (t, a) =>
|
430 |
0 |
{
|
431 |
0 |
ConstructorInfo c = t.GetConstructor(new[] {listDefinition});
|
432 |
0 |
return c.Invoke(new[] { list });
|
433 |
0 |
};
|
434 |
||
435 |
0 |
return (IWrappedList)ReflectionUtils.CreateGeneric(typeof(ListWrapper<>), new[] { collectionItemType }, instanceCreator, list);
|
436 |
} |
|
437 |
0 |
else if (list is IList)
|
438 |
{ |
|
439 |
0 |
return new ListWrapper<object>((IList)list);
|
440 |
} |
|
441 |
else |
|
442 |
{ |
|
443 |
0 |
throw new Exception("Can not create ListWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, list.GetType()));
|
444 |
} |
|
445 |
0 |
}
|
446 |
||
447 |
public static IWrappedDictionary CreateDictionaryWrapper(object dictionary) |
|
448 |
{ |
|
449 |
1 |
ValidationUtils.ArgumentNotNull(dictionary, "dictionary");
|
450 |
||
451 |
Type dictionaryDefinition; |
|
452 |
1 |
if (ReflectionUtils.ImplementsGenericDefinition(dictionary.GetType(), typeof(IDictionary<,>), out dictionaryDefinition))
|
453 |
{ |
|
454 |
1 |
Type dictionaryKeyType = ReflectionUtils.GetDictionaryKeyType(dictionaryDefinition);
|
455 |
1 |
Type dictionaryValueType = ReflectionUtils.GetDictionaryValueType(dictionaryDefinition);
|
456 |
||
457 |
// Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor |
|
458 |
1 |
Func<Type, IList<object>, object> instanceCreator = (t, a) =>
|
459 |
1 |
{
|
460 |
1 |
ConstructorInfo c = t.GetConstructor(new[] { dictionaryDefinition });
|
461 |
1 |
return c.Invoke(new[] { dictionary });
|
462 |
1 |
};
|
463 |
||
464 |
1 |
return (IWrappedDictionary)ReflectionUtils.CreateGeneric(typeof(DictionaryWrapper<,>), new[] { dictionaryKeyType, dictionaryValueType }, instanceCreator, dictionary);
|
465 |
} |
|
466 |
0 |
else if (dictionary is IDictionary)
|
467 |
{ |
|
468 |
0 |
return new DictionaryWrapper<object, object>((IDictionary)dictionary);
|
469 |
} |
|
470 |
else |
|
471 |
{ |
|
472 |
0 |
throw new Exception("Can not create DictionaryWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, dictionary.GetType()));
|
473 |
} |
|
474 |
1 |
}
|
475 |
||
476 |
public static object CreateAndPopulateList(Type listType, Action<IList, bool> populateList) |
|
477 |
{ |
|
478 |
20079 |
ValidationUtils.ArgumentNotNull(listType, "listType");
|
479 |
20079 |
ValidationUtils.ArgumentNotNull(populateList, "populateList");
|
480 |
||
481 |
IList list; |
|
482 |
Type collectionType; |
|
483 |
20079 |
bool isReadOnlyOrFixedSize = false;
|
484 |
||
485 |
20079 |
if (listType.IsArray)
|
486 |
{ |
|
487 |
// have to use an arraylist when creating array |
|
488 |
// there is no way to know the size until it is finised |
|
489 |
27 |
list = new List<object>();
|
490 |
27 |
isReadOnlyOrFixedSize = true;
|
491 |
} |
|
492 |
20052 |
else if (ReflectionUtils.InheritsGenericDefinition(listType, typeof(ReadOnlyCollection<>), out collectionType))
|
493 |
{ |
|
494 |
1 |
Type readOnlyCollectionContentsType = collectionType.GetGenericArguments()[0];
|
495 |
1 |
Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), readOnlyCollectionContentsType);
|
496 |
1 |
bool suitableConstructor = false;
|
497 |
||
498 |
1 |
foreach (ConstructorInfo constructor in listType.GetConstructors())
|
499 |
{ |
|
500 |
1 |
IList<ParameterInfo> parameters = constructor.GetParameters();
|
501 |
||
502 |
1 |
if (parameters.Count == 1)
|
503 |
{ |
|
504 |
1 |
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
505 |
{ |
|
506 |
1 |
suitableConstructor = true;
|
507 |
1 |
break;
|
508 |
} |
|
509 |
} |
|
510 |
} |
|
511 |
||
512 |
1 |
if (!suitableConstructor)
|
513 |
0 |
throw new Exception("Read-only type {0} does not have a public constructor that takes a type that implements {1}.".FormatWith(CultureInfo.InvariantCulture, listType, genericEnumerable));
|
514 |
||
515 |
// can't add or modify a readonly list |
|
516 |
// use List<T> and convert once populated |
|
517 |
1 |
list = CreateGenericList(readOnlyCollectionContentsType);
|
518 |
1 |
isReadOnlyOrFixedSize = true;
|
519 |
} |
|
520 |
20051 |
else if (typeof(IList).IsAssignableFrom(listType))
|
521 |
{ |
|
522 |
20050 |
if (ReflectionUtils.IsInstantiatableType(listType))
|
523 |
20050 |
list = (IList)Activator.CreateInstance(listType);
|
524 |
0 |
else if (listType == typeof(IList))
|
525 |
0 |
list = new List<object>();
|
526 |
else |
|
527 |
0 |
list = null;
|
528 |
} |
|
529 |
1 |
else if (ReflectionUtils.ImplementsGenericDefinition(listType, typeof(ICollection<>)))
|
530 |
{ |
|
531 |
1 |
if (ReflectionUtils.IsInstantiatableType(listType))
|
532 |
1 |
list = CreateCollectionWrapper(Activator.CreateInstance(listType));
|
533 |
else |
|
534 |
0 |
list = null;
|
535 |
} |
|
536 |
else |
|
537 |
{ |
|
538 |
0 |
list = null;
|
539 |
} |
|
540 |
||
541 |
20079 |
if (list == null)
|
542 |
0 |
throw new Exception("Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, listType));
|
543 |
||
544 |
20079 |
populateList(list, isReadOnlyOrFixedSize);
|
545 |
||
546 |
// create readonly and fixed sized collections using the temporary list |
|
547 |
20075 |
if (isReadOnlyOrFixedSize)
|
548 |
{ |
|
549 |
27 |
if (listType.IsArray)
|
550 |
26 |
list = ToArray(((List<object>)list).ToArray(), ReflectionUtils.GetCollectionItemType(listType));
|
551 |
1 |
else if (ReflectionUtils.InheritsGenericDefinition(listType, typeof(ReadOnlyCollection<>)))
|
552 |
1 |
list = (IList)ReflectionUtils.CreateInstance(listType, list);
|
553 |
} |
|
554 |
20048 |
else if (list is IWrappedCollection)
|
555 |
{ |
|
556 |
1 |
return ((IWrappedCollection) list).UnderlyingCollection;
|
557 |
} |
|
558 |
||
559 |
20074 |
return list;
|
560 |
20075 |
}
|
561 |
||
562 |
public static Array ToArray(Array initial, Type type) |
|
563 |
{ |
|
564 |
26 |
if (type == null)
|
565 |
0 |
throw new ArgumentNullException("type");
|
566 |
||
567 |
26 |
Array destinationArray = Array.CreateInstance(type, initial.Length);
|
568 |
26 |
Array.Copy(initial, 0, destinationArray, 0, initial.Length);
|
569 |
26 |
return destinationArray;
|
570 |
26 |
}
|
571 |
||
572 |
public static bool AddDistinct<T>(this IList<T> list, T value) |
|
573 |
{ |
|
574 |
9 |
return list.AddDistinct(value, EqualityComparer<T>.Default);
|
575 |
9 |
}
|
576 |
||
577 |
public static bool AddDistinct<T>(this IList<T> list, T value, IEqualityComparer<T> comparer) |
|
578 |
{ |
|
579 |
24 |
if (list.ContainsValue(value, comparer))
|
580 |
2 |
return false;
|
581 |
||
582 |
22 |
list.Add(value);
|
583 |
22 |
return true;
|
584 |
24 |
}
|
585 |
||
586 |
// this is here because LINQ Bridge doesn't support Contains with IEqualityComparer<T> |
|
587 |
public static bool ContainsValue<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer) |
|
588 |
{ |
|
589 |
37 |
if (comparer == null)
|
590 |
0 |
comparer = EqualityComparer<TSource>.Default;
|
591 |
||
592 |
37 |
if (source == null)
|
593 |
0 |
throw new ArgumentNullException("source");
|
594 |
||
595 |
32 |
foreach (TSource local in source)
|
596 |
{ |
|
597 |
32 |
if (comparer.Equals(local, value))
|
598 |
10 |
return true;
|
599 |
} |
|
600 |
||
601 |
27 |
return false;
|
602 |
37 |
}
|
603 |
||
604 |
public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values) |
|
605 |
{ |
|
606 |
0 |
return list.AddRangeDistinct(values, EqualityComparer<T>.Default);
|
607 |
0 |
}
|
608 |
||
609 |
public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values, IEqualityComparer<T> comparer) |
|
610 |
{ |
|
611 |
9 |
bool allAdded = true;
|
612 |
9 |
foreach (T value in values)
|
613 |
{ |
|
614 |
15 |
if (!list.AddDistinct(value, comparer))
|
615 |
2 |
allAdded = false;
|
616 |
} |
|
617 |
||
618 |
9 |
return allAdded;
|
619 |
9 |
}
|
620 |
||
621 |
public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> predicate) |
|
622 |
{ |
|
623 |
30 |
int index = 0;
|
624 |
30 |
foreach (T value in collection)
|
625 |
{ |
|
626 |
357 |
if (predicate(value))
|
627 |
16 |
return index;
|
628 |
||
629 |
341 |
index++;
|
630 |
} |
|
631 |
||
632 |
14 |
return -1;
|
633 |
30 |
}
|
634 |
} |
|
635 |
} |