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.Collections.Specialized;
16
using System.Reflection;
17
using System.Threading;
19
namespace ServiceStack.Text.Common
21
internal static class DeserializeArrayWithElements<TSerializer>
22
where TSerializer : ITypeSerializer
24
private static Dictionary<Type, ParseArrayOfElementsDelegate> ParseDelegateCache
25
= new Dictionary<Type, ParseArrayOfElementsDelegate>();
27
private delegate object ParseArrayOfElementsDelegate(string value, ParseStringDelegate parseFn);
29
public static Func<string, ParseStringDelegate, object> GetParseFn(Type type)
31
ParseArrayOfElementsDelegate parseFn;
32
if (ParseDelegateCache.TryGetValue(type, out parseFn)) return parseFn.Invoke;
34
var genericType = typeof(DeserializeArrayWithElements<,>).MakeGenericType(type, typeof(TSerializer));
35
var mi = genericType.GetMethod("ParseGenericArray", BindingFlags.Public | BindingFlags.Static);
36
parseFn = (ParseArrayOfElementsDelegate)Delegate.CreateDelegate(typeof(ParseArrayOfElementsDelegate), mi);
38
Dictionary<Type, ParseArrayOfElementsDelegate> snapshot, newCache;
41
snapshot = ParseDelegateCache;
42
newCache = new Dictionary<Type, ParseArrayOfElementsDelegate>(ParseDelegateCache);
43
newCache[type] = parseFn;
45
} while (!ReferenceEquals(
46
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
48
return parseFn.Invoke;
52
internal static class DeserializeArrayWithElements<T, TSerializer>
53
where TSerializer : ITypeSerializer
55
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
57
public static T[] ParseGenericArray(string value, ParseStringDelegate elementParseFn)
59
if ((value = DeserializeListWithElements<TSerializer>.StripList(value)) == null) return null;
60
if (value == string.Empty) return new T[0];
62
if (value[0] == JsWriter.MapStartChar)
64
var itemValues = new List<string>();
68
itemValues.Add(Serializer.EatTypeValue(value, ref i));
69
} while (++i < value.Length);
71
var results = new T[itemValues.Count];
72
for (var j=0; j < itemValues.Count; j++)
74
results[j] = (T)elementParseFn(itemValues[j]);
80
var to = new List<T>();
81
var valueLength = value.Length;
84
while (i < valueLength)
86
var elementValue = Serializer.EatValue(value, ref i);
87
var listValue = elementValue;
88
to.Add((T)elementParseFn(listValue));
89
Serializer.EatItemSeperatorOrMapEndChar(value, ref i);
97
internal static class DeserializeArray<TSerializer>
98
where TSerializer : ITypeSerializer
100
private static Dictionary<Type, ParseStringDelegate> ParseDelegateCache = new Dictionary<Type, ParseStringDelegate>();
102
public static ParseStringDelegate GetParseFn(Type type)
104
ParseStringDelegate parseFn;
105
if (ParseDelegateCache.TryGetValue(type, out parseFn)) return parseFn;
107
var genericType = typeof(DeserializeArray<,>).MakeGenericType(type, typeof(TSerializer));
108
var mi = genericType.GetMethod("GetParseFn", BindingFlags.Public | BindingFlags.Static);
109
var parseFactoryFn = (Func<ParseStringDelegate>)Delegate.CreateDelegate(
110
typeof(Func<ParseStringDelegate>), mi);
111
parseFn = parseFactoryFn();
113
Dictionary<Type, ParseStringDelegate> snapshot, newCache;
116
snapshot = ParseDelegateCache;
117
newCache = new Dictionary<Type, ParseStringDelegate>(ParseDelegateCache);
118
newCache[type] = parseFn;
120
} while (!ReferenceEquals(
121
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
127
internal static class DeserializeArray<T, TSerializer>
128
where TSerializer : ITypeSerializer
130
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
132
private static readonly ParseStringDelegate CacheFn;
134
static DeserializeArray()
136
CacheFn = GetParseFn();
139
public static ParseStringDelegate Parse
141
get { return CacheFn; }
144
public static ParseStringDelegate GetParseFn()
146
var type = typeof (T);
148
throw new ArgumentException(string.Format("Type {0} is not an Array type", type.FullName));
150
if (type == typeof(string[]))
151
return ParseStringArray;
152
if (type == typeof(byte[]))
153
return ParseByteArray;
155
var elementType = type.GetElementType();
156
var elementParseFn = Serializer.GetParseFn(elementType);
157
if (elementParseFn != null)
159
var parseFn = DeserializeArrayWithElements<TSerializer>.GetParseFn(elementType);
160
return value => parseFn(value, elementParseFn);
165
public static string[] ParseStringArray(string value)
167
if ((value = DeserializeListWithElements<TSerializer>.StripList(value)) == null) return null;
168
return value == string.Empty
170
: DeserializeListWithElements<TSerializer>.ParseStringList(value).ToArray();
173
public static byte[] ParseByteArray(string value)
175
if ((value = DeserializeListWithElements<TSerializer>.StripList(value)) == null) return null;
176
if ((value = Serializer.ParseRawString(value)) == null) return null;
177
return value == string.Empty
179
: Convert.FromBase64String(value);
b'\\ No newline at end of file'