~ubuntu-branches/ubuntu/trusty/smuxi/trusty-proposed

« back to all changes in this revision

Viewing changes to lib/ServiceStack.Text/src/ServiceStack.Text/Common/DeserializeType.cs

  • Committer: Package Import Robot
  • Author(s): Mirco Bauer
  • Date: 2013-05-25 22:11:31 UTC
  • mfrom: (1.2.12)
  • Revision ID: package-import@ubuntu.com-20130525221131-nd2mc0kzubuwyx20
Tags: 0.8.11-1
* [22d13d5] Imported Upstream version 0.8.11
* [6d2b95a] Refreshed patches
* [89eb66e] Added ServiceStack libraries to smuxi-engine package
* [848ab10] Enable Campfire engine
* [c6dbdc7] Always build db4o for predictable build result
* [13ec489] Exclude OS X specific libraries from dh_clideps

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// http://code.google.com/p/servicestack/wiki/TypeSerializer
 
3
// ServiceStack.Text: .NET C# POCO Type Text Serializer.
 
4
//
 
5
// Authors:
 
6
//   Demis Bellot (demis.bellot@gmail.com)
 
7
//
 
8
// Copyright 2011 Liquidbit Ltd.
 
9
//
 
10
// Licensed under the same terms of ServiceStack: new BSD license.
 
11
//
 
12
 
 
13
#if !XBOX && !MONOTOUCH && !SILVERLIGHT
 
14
using System.Reflection.Emit;
 
15
#endif
 
16
 
 
17
using System;
 
18
using System.Collections.Generic;
 
19
using System.Reflection;
 
20
using System.Runtime.Serialization;
 
21
using System.Linq;
 
22
 
 
23
namespace ServiceStack.Text.Common
 
24
{
 
25
        internal static class DeserializeType<TSerializer>
 
26
                where TSerializer : ITypeSerializer
 
27
        {
 
28
                private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
 
29
 
 
30
                private static readonly string TypeAttrInObject = Serializer.TypeAttrInObject;
 
31
 
 
32
                public static ParseStringDelegate GetParseMethod(TypeConfig typeConfig)
 
33
                {
 
34
                        var type = typeConfig.Type;
 
35
 
 
36
                        if (!type.IsClass || type.IsAbstract || type.IsInterface) return null;
 
37
 
 
38
                        var propertyInfos = type.GetSerializableProperties();
 
39
                        if (propertyInfos.Length == 0)
 
40
                        {
 
41
                                var emptyCtorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
 
42
                                return value => emptyCtorFn();
 
43
                        }
 
44
 
 
45
                        var map = new Dictionary<string, TypeAccessor>(StringComparer.OrdinalIgnoreCase);
 
46
 
 
47
                        var isDataContract = type.GetCustomAttributes(typeof(DataContractAttribute), false).Any();
 
48
 
 
49
                        foreach (var propertyInfo in propertyInfos)
 
50
                        {
 
51
                                var propertyName = propertyInfo.Name;
 
52
                                if (isDataContract)
 
53
                                {
 
54
                                        var dcsDataMember = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() as DataMemberAttribute;
 
55
                                        if (dcsDataMember != null && dcsDataMember.Name != null)
 
56
                                        {
 
57
                                                propertyName = dcsDataMember.Name;
 
58
                                        }
 
59
                                }
 
60
                                map[propertyName] = TypeAccessor.Create(Serializer, typeConfig, propertyInfo);
 
61
                        }
 
62
 
 
63
                        var ctorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
 
64
 
 
65
                        return typeof(TSerializer) == typeof(Json.JsonTypeSerializer)
 
66
                                ? (ParseStringDelegate)(value => DeserializeTypeRefJson.StringToType(type, value, ctorFn, map))
 
67
                                : value => DeserializeTypeRefJsv.StringToType(type, value, ctorFn, map);
 
68
                }
 
69
 
 
70
                public static object ObjectStringToType(string strType)
 
71
                {
 
72
                        var type = ExtractType(strType);
 
73
                        if (type != null)
 
74
                        {
 
75
                                var parseFn = Serializer.GetParseFn(type);
 
76
                                var propertyValue = parseFn(strType);
 
77
                                return propertyValue;
 
78
                        }
 
79
 
 
80
                        return strType;
 
81
                }
 
82
 
 
83
                public static Type ExtractType(string strType)
 
84
                {
 
85
                        if (strType != null
 
86
                                && strType.Length > TypeAttrInObject.Length
 
87
                                && strType.Substring(0, TypeAttrInObject.Length) == TypeAttrInObject)
 
88
                        {
 
89
                                var propIndex = TypeAttrInObject.Length;
 
90
                                var typeName = Serializer.EatValue(strType, ref propIndex);
 
91
                                var type = AssemblyUtils.FindType(typeName);
 
92
 
 
93
                                if (type == null)
 
94
                                        Tracer.Instance.WriteWarning("Could not find type: " + typeName);
 
95
 
 
96
                                return type;
 
97
                        }
 
98
                        return null;
 
99
                }
 
100
 
 
101
                public static object ParseAbstractType<T>(string value)
 
102
                {
 
103
                        if (typeof(T).IsAbstract)
 
104
                        {
 
105
                                if (string.IsNullOrEmpty(value)) return null;
 
106
                                var concreteType = ExtractType(value);
 
107
                                if (concreteType != null)
 
108
                                {
 
109
                                        return Serializer.GetParseFn(concreteType)(value);
 
110
                                }
 
111
                                Tracer.Instance.WriteWarning(
 
112
                                        "Could not deserialize Abstract Type with unknown concrete type: " + typeof(T).FullName);
 
113
                        }
 
114
                        return null;
 
115
                }
 
116
 
 
117
        }
 
118
 
 
119
        internal class TypeAccessor
 
120
        {
 
121
                internal ParseStringDelegate GetProperty;
 
122
                internal SetPropertyDelegate SetProperty;
 
123
 
 
124
                public static Type ExtractType(ITypeSerializer Serializer, string strType)
 
125
                {
 
126
                        var TypeAttrInObject = Serializer.TypeAttrInObject;
 
127
 
 
128
                        if (strType != null
 
129
                                && strType.Length > TypeAttrInObject.Length
 
130
                                && strType.Substring(0, TypeAttrInObject.Length) == TypeAttrInObject)
 
131
                        {
 
132
                                var propIndex = TypeAttrInObject.Length;
 
133
                                var typeName = Serializer.EatValue(strType, ref propIndex);
 
134
                                var type = AssemblyUtils.FindType(typeName);
 
135
 
 
136
                                if (type == null)
 
137
                                        Tracer.Instance.WriteWarning("Could not find type: " + typeName);
 
138
 
 
139
                                return type;
 
140
                        }
 
141
                        return null;
 
142
                }
 
143
 
 
144
                public static TypeAccessor Create(ITypeSerializer serializer, TypeConfig typeConfig, PropertyInfo propertyInfo)
 
145
                {
 
146
                        return new TypeAccessor {
 
147
                                GetProperty = serializer.GetParseFn(propertyInfo.PropertyType),
 
148
                                SetProperty = GetSetPropertyMethod(typeConfig, propertyInfo),
 
149
                        };
 
150
                }
 
151
 
 
152
                private static SetPropertyDelegate GetSetPropertyMethod(TypeConfig typeConfig, PropertyInfo propertyInfo)
 
153
                {
 
154
                        if (!propertyInfo.CanWrite && !typeConfig.EnableAnonymousFieldSetterses) return null;
 
155
 
 
156
                        FieldInfo fieldInfo = null;
 
157
                        if (!propertyInfo.CanWrite)
 
158
                        {
 
159
                                //TODO: What string comparison is used in SST?
 
160
                                var fieldName = string.Format("<{0}>i__Field", propertyInfo.Name);
 
161
                                var fieldInfos = typeConfig.Type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
 
162
                                foreach (var f in fieldInfos)
 
163
                                {
 
164
                                        if (f.IsInitOnly && f.FieldType == propertyInfo.PropertyType && f.Name == fieldName)
 
165
                                        {
 
166
                                                fieldInfo = f;
 
167
                                                break;
 
168
                                        }
 
169
                                }
 
170
 
 
171
                                if (fieldInfo == null) return null;
 
172
                        }
 
173
 
 
174
#if SILVERLIGHT || MONOTOUCH || XBOX
 
175
                        if (propertyInfo.CanWrite)
 
176
                        {
 
177
                                var setMethodInfo = propertyInfo.GetSetMethod(true);
 
178
                                return (instance, value) => setMethodInfo.Invoke(instance, new[] { value });
 
179
                        }
 
180
                        if (fieldInfo == null) return null;
 
181
                        return (instance, value) => fieldInfo.SetValue(instance, value);
 
182
#else
 
183
                        return propertyInfo.CanWrite
 
184
                                ? CreateIlPropertySetter(propertyInfo)
 
185
                                : CreateIlFieldSetter(fieldInfo);
 
186
#endif
 
187
                }
 
188
 
 
189
#if !SILVERLIGHT && !MONOTOUCH && !XBOX
 
190
 
 
191
                private static SetPropertyDelegate CreateIlPropertySetter(PropertyInfo propertyInfo)
 
192
                {
 
193
                        var propSetMethod = propertyInfo.GetSetMethod(true);
 
194
                        if (propSetMethod == null)
 
195
                                return null;
 
196
 
 
197
                        var setter = CreateDynamicSetMethod(propertyInfo);
 
198
 
 
199
                        var generator = setter.GetILGenerator();
 
200
                        generator.Emit(OpCodes.Ldarg_0);
 
201
                        generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
 
202
                        generator.Emit(OpCodes.Ldarg_1);
 
203
 
 
204
                        generator.Emit(propertyInfo.PropertyType.IsClass
 
205
                                ? OpCodes.Castclass
 
206
                                : OpCodes.Unbox_Any,
 
207
                                propertyInfo.PropertyType);
 
208
 
 
209
                        generator.EmitCall(OpCodes.Callvirt, propSetMethod, (Type[])null);
 
210
                        generator.Emit(OpCodes.Ret);
 
211
 
 
212
                        return (SetPropertyDelegate)setter.CreateDelegate(typeof(SetPropertyDelegate));
 
213
                }
 
214
 
 
215
                private static SetPropertyDelegate CreateIlFieldSetter(FieldInfo fieldInfo)
 
216
                {
 
217
                        var setter = CreateDynamicSetMethod(fieldInfo);
 
218
 
 
219
                        var generator = setter.GetILGenerator();
 
220
                        generator.Emit(OpCodes.Ldarg_0);
 
221
                        generator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
 
222
                        generator.Emit(OpCodes.Ldarg_1);
 
223
 
 
224
                        generator.Emit(fieldInfo.FieldType.IsClass
 
225
                                ? OpCodes.Castclass
 
226
                                : OpCodes.Unbox_Any,
 
227
                                fieldInfo.FieldType);
 
228
 
 
229
                        generator.Emit(OpCodes.Stfld, fieldInfo);
 
230
                        generator.Emit(OpCodes.Ret);
 
231
 
 
232
                        return (SetPropertyDelegate)setter.CreateDelegate(typeof(SetPropertyDelegate));
 
233
                }
 
234
 
 
235
                private static DynamicMethod CreateDynamicSetMethod(MemberInfo memberInfo)
 
236
                {
 
237
                        var args = new[] { typeof(object), typeof(object) };
 
238
                        var name = string.Format("_{0}{1}_", "Set", memberInfo.Name);
 
239
                        var returnType = typeof(void);
 
240
 
 
241
                        return !memberInfo.DeclaringType.IsInterface
 
242
                                ? new DynamicMethod(name, returnType, args, memberInfo.DeclaringType, true)
 
243
                                : new DynamicMethod(name, returnType, args, memberInfo.Module, true);
 
244
                }
 
245
#endif
 
246
 
 
247
                internal static SetPropertyDelegate GetSetPropertyMethod(Type type, PropertyInfo propertyInfo)
 
248
                {
 
249
                        if (!propertyInfo.CanWrite) return null;
 
250
 
 
251
#if SILVERLIGHT || MONOTOUCH || XBOX
 
252
                        var setMethodInfo = propertyInfo.GetSetMethod(true);
 
253
                        return (instance, value) => setMethodInfo.Invoke(instance, new[] { value });
 
254
#else
 
255
                        return CreateIlPropertySetter(propertyInfo);
 
256
#endif
 
257
                }
 
258
        }
 
259
}