2
// http://code.google.com/p/servicestack/wiki/TypeSerializer
3
// ServiceStack.Text: .NET C# POCO Type Text Serializer.
6
// Demis Bellot (demis.bellot@gmail.com)
8
// Copyright 2011 Liquidbit Ltd.
10
// Licensed under the same terms of ServiceStack: new BSD license.
14
using System.Collections.Generic;
15
using System.Reflection;
16
using System.Threading;
18
namespace ServiceStack.Text.Common
20
internal static class DeserializeCollection<TSerializer>
21
where TSerializer : ITypeSerializer
23
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
25
public static ParseStringDelegate GetParseMethod(Type type)
27
var collectionInterface = type.GetTypeWithGenericInterfaceOf(typeof(ICollection<>));
28
if (collectionInterface == null)
29
throw new ArgumentException(string.Format("Type {0} is not of type ICollection<>", type.FullName));
31
//optimized access for regularly used types
32
if (type.HasInterface(typeof(ICollection<string>)))
33
return value => ParseStringCollection(value, type);
35
if (type.HasInterface(typeof(ICollection<int>)))
36
return value => ParseIntCollection(value, type);
38
var elementType = collectionInterface.GetGenericArguments()[0];
40
var supportedTypeParseMethod = Serializer.GetParseFn(elementType);
41
if (supportedTypeParseMethod != null)
43
var createCollectionType = type.HasAnyTypeDefinitionsOf(typeof(ICollection<>))
46
return value => ParseCollectionType(value, createCollectionType, elementType, supportedTypeParseMethod);
52
public static ICollection<string> ParseStringCollection(string value, Type createType)
54
var items = DeserializeArrayWithElements<string, TSerializer>.ParseGenericArray(value, Serializer.ParseString);
55
return CreateAndPopulate(createType, items);
58
public static ICollection<int> ParseIntCollection(string value, Type createType)
60
var items = DeserializeArrayWithElements<int, TSerializer>.ParseGenericArray(value, x => int.Parse(x));
61
return CreateAndPopulate(createType, items);
64
public static ICollection<T> ParseCollection<T>(string value, Type createType, ParseStringDelegate parseFn)
66
if (value == null) return null;
68
var items = DeserializeArrayWithElements<T, TSerializer>.ParseGenericArray(value, parseFn);
69
return CreateAndPopulate(createType, items);
72
private static ICollection<T> CreateAndPopulate<T>(Type ofCollectionType, T[] withItems)
74
if (ofCollectionType == null) return new List<T>(withItems);
76
var genericTypeDefinition = ofCollectionType.IsGenericType()
77
? ofCollectionType.GetGenericTypeDefinition()
80
if (genericTypeDefinition == typeof(HashSet<T>))
81
return new HashSet<T>(withItems);
83
if (genericTypeDefinition == typeof(LinkedList<T>))
84
return new LinkedList<T>(withItems);
86
var collection = (ICollection<T>)ofCollectionType.CreateInstance();
87
foreach (var item in withItems)
94
private static Dictionary<Type, ParseCollectionDelegate> ParseDelegateCache
95
= new Dictionary<Type, ParseCollectionDelegate>();
97
private delegate object ParseCollectionDelegate(string value, Type createType, ParseStringDelegate parseFn);
99
public static object ParseCollectionType(string value, Type createType, Type elementType, ParseStringDelegate parseFn)
101
ParseCollectionDelegate parseDelegate;
102
if (ParseDelegateCache.TryGetValue(elementType, out parseDelegate))
103
return parseDelegate(value, createType, parseFn);
105
var mi = typeof(DeserializeCollection<TSerializer>).GetMethod("ParseCollection", BindingFlags.Static | BindingFlags.Public);
106
var genericMi = mi.MakeGenericMethod(new[] { elementType });
107
parseDelegate = (ParseCollectionDelegate)Delegate.CreateDelegate(typeof(ParseCollectionDelegate), genericMi);
109
Dictionary<Type, ParseCollectionDelegate> snapshot, newCache;
112
snapshot = ParseDelegateCache;
113
newCache = new Dictionary<Type, ParseCollectionDelegate>(ParseDelegateCache);
114
newCache[elementType] = parseDelegate;
116
} while (!ReferenceEquals(
117
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
119
return parseDelegate(value, createType, parseFn);
b'\\ No newline at end of file'