Skip to content

Commit 22ba0c2

Browse files
committed
handle classes with no public properties or no properties with getters
1 parent 25ca8f9 commit 22ba0c2

5 files changed

Lines changed: 748 additions & 726 deletions

File tree

Lines changed: 123 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,124 @@
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 2010 Liquidbit Ltd.
9-
//
10-
// Licensed under the same terms of ServiceStack: new BSD license.
11-
//
12-
13-
using System;
14-
using System.Collections.Generic;
15-
using System.Linq.Expressions;
16-
using System.Reflection;
17-
using System.Runtime.Serialization;
18-
using System.Text;
19-
20-
namespace ServiceStack.Text.Common
21-
{
22-
internal static class DeserializeType<TSerializer>
23-
where TSerializer : ITypeSerializer
24-
{
25-
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
26-
27-
public static ParseStringDelegate GetParseMethod(Type type)
28-
{
29-
if (!type.IsClass) return null;
30-
31-
var propertyInfos = type.GetProperties();
32-
if (propertyInfos.Length == 0)
33-
{
34-
if (type.IsDto())
35-
{
36-
var emptyCtorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
37-
return value => emptyCtorFn();
38-
}
39-
return null;
40-
}
41-
42-
43-
var setterMap = new Dictionary<string, SetPropertyDelegate>();
44-
var map = new Dictionary<string, ParseStringDelegate>();
45-
46-
foreach (var propertyInfo in propertyInfos)
47-
{
48-
map[propertyInfo.Name] = Serializer.GetParseFn(propertyInfo.PropertyType);
49-
setterMap[propertyInfo.Name] = GetSetPropertyMethod(type, propertyInfo);
50-
}
51-
52-
var ctorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
53-
return value => StringToType(type, value, ctorFn, setterMap, map);
54-
}
55-
56-
private static object StringToType(Type type, string strType,
57-
EmptyCtorDelegate ctorFn,
58-
IDictionary<string, SetPropertyDelegate> setterMap,
59-
IDictionary<string, ParseStringDelegate> parseStringFnMap)
60-
{
61-
var index = 0;
62-
63-
if (!Serializer.EatMapStartChar(strType, ref index))
64-
throw new SerializationException(string.Format(
65-
"Type definitions should start with a '{0}', expecting serialized type '{1}', got string starting with: {2}",
66-
JsWriter.MapStartChar, type.Name, strType.Substring(0, strType.Length < 50 ? strType.Length : 50)));
67-
68-
69-
var instance = ctorFn();
70-
string propertyName;
71-
ParseStringDelegate parseStringFn;
72-
SetPropertyDelegate setterFn;
73-
74-
if (strType == JsWriter.EmptyMap) return instance;
75-
var strTypeLength = strType.Length;
76-
77-
while (index < strTypeLength)
78-
{
79-
propertyName = Serializer.EatMapKey(strType, ref index);
80-
81-
Serializer.EatMapKeySeperator(strType, ref index);
82-
83-
var propertyValueString = Serializer.EatValue(strType, ref index);
84-
85-
parseStringFnMap.TryGetValue(propertyName, out parseStringFn);
86-
87-
if (parseStringFn != null)
88-
{
89-
var propertyValue = parseStringFn(propertyValueString);
90-
91-
setterMap.TryGetValue(propertyName, out setterFn);
92-
93-
if (setterFn != null)
94-
{
95-
setterFn(instance, propertyValue);
96-
}
97-
}
98-
99-
Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
100-
}
101-
102-
return instance;
103-
}
104-
105-
public static SetPropertyDelegate GetSetPropertyMethod(Type type, PropertyInfo propertyInfo)
106-
{
107-
var setMethodInfo = propertyInfo.GetSetMethod(true);
108-
if (setMethodInfo == null) return null;
109-
var oInstanceParam = Expression.Parameter(typeof(object), "oInstanceParam");
110-
var oValueParam = Expression.Parameter(typeof(object), "oValueParam");
111-
112-
var instanceParam = Expression.Convert(oInstanceParam, type);
113-
var useType = propertyInfo.PropertyType;
114-
115-
var valueParam = Expression.Convert(oValueParam, useType);
116-
var exprCallPropertySetFn = Expression.Call(instanceParam, setMethodInfo, valueParam);
117-
118-
var propertySetFn = Expression.Lambda<SetPropertyDelegate>
119-
(
120-
exprCallPropertySetFn,
121-
oInstanceParam,
122-
oValueParam
123-
).Compile();
124-
125-
return propertySetFn;
126-
}
127-
}
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 2010 Liquidbit Ltd.
9+
//
10+
// Licensed under the same terms of ServiceStack: new BSD license.
11+
//
12+
13+
using System;
14+
using System.Collections.Generic;
15+
using System.Linq.Expressions;
16+
using System.Reflection;
17+
using System.Runtime.Serialization;
18+
using System.Text;
19+
20+
namespace ServiceStack.Text.Common
21+
{
22+
internal static class DeserializeType<TSerializer>
23+
where TSerializer : ITypeSerializer
24+
{
25+
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
26+
27+
public static ParseStringDelegate GetParseMethod(Type type)
28+
{
29+
if (!type.IsClass) return null;
30+
31+
var propertyInfos = type.GetProperties();
32+
if (propertyInfos.Length == 0)
33+
{
34+
var emptyCtorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
35+
return value => emptyCtorFn();
36+
}
37+
38+
39+
var setterMap = new Dictionary<string, SetPropertyDelegate>();
40+
var map = new Dictionary<string, ParseStringDelegate>();
41+
42+
foreach (var propertyInfo in propertyInfos)
43+
{
44+
map[propertyInfo.Name] = Serializer.GetParseFn(propertyInfo.PropertyType);
45+
setterMap[propertyInfo.Name] = GetSetPropertyMethod(type, propertyInfo);
46+
}
47+
48+
var ctorFn = ReflectionExtensions.GetConstructorMethodToCache(type);
49+
return value => StringToType(type, value, ctorFn, setterMap, map);
50+
}
51+
52+
private static object StringToType(Type type, string strType,
53+
EmptyCtorDelegate ctorFn,
54+
IDictionary<string, SetPropertyDelegate> setterMap,
55+
IDictionary<string, ParseStringDelegate> parseStringFnMap)
56+
{
57+
var index = 0;
58+
59+
if (!Serializer.EatMapStartChar(strType, ref index))
60+
throw new SerializationException(string.Format(
61+
"Type definitions should start with a '{0}', expecting serialized type '{1}', got string starting with: {2}",
62+
JsWriter.MapStartChar, type.Name, strType.Substring(0, strType.Length < 50 ? strType.Length : 50)));
63+
64+
65+
var instance = ctorFn();
66+
string propertyName;
67+
ParseStringDelegate parseStringFn;
68+
SetPropertyDelegate setterFn;
69+
70+
if (strType == JsWriter.EmptyMap) return instance;
71+
var strTypeLength = strType.Length;
72+
73+
while (index < strTypeLength)
74+
{
75+
propertyName = Serializer.EatMapKey(strType, ref index);
76+
77+
Serializer.EatMapKeySeperator(strType, ref index);
78+
79+
var propertyValueString = Serializer.EatValue(strType, ref index);
80+
81+
parseStringFnMap.TryGetValue(propertyName, out parseStringFn);
82+
83+
if (parseStringFn != null)
84+
{
85+
var propertyValue = parseStringFn(propertyValueString);
86+
87+
setterMap.TryGetValue(propertyName, out setterFn);
88+
89+
if (setterFn != null)
90+
{
91+
setterFn(instance, propertyValue);
92+
}
93+
}
94+
95+
Serializer.EatItemSeperatorOrMapEndChar(strType, ref index);
96+
}
97+
98+
return instance;
99+
}
100+
101+
public static SetPropertyDelegate GetSetPropertyMethod(Type type, PropertyInfo propertyInfo)
102+
{
103+
var setMethodInfo = propertyInfo.GetSetMethod(true);
104+
if (setMethodInfo == null) return null;
105+
var oInstanceParam = Expression.Parameter(typeof(object), "oInstanceParam");
106+
var oValueParam = Expression.Parameter(typeof(object), "oValueParam");
107+
108+
var instanceParam = Expression.Convert(oInstanceParam, type);
109+
var useType = propertyInfo.PropertyType;
110+
111+
var valueParam = Expression.Convert(oValueParam, useType);
112+
var exprCallPropertySetFn = Expression.Call(instanceParam, setMethodInfo, valueParam);
113+
114+
var propertySetFn = Expression.Lambda<SetPropertyDelegate>
115+
(
116+
exprCallPropertySetFn,
117+
oInstanceParam,
118+
oValueParam
119+
).Compile();
120+
121+
return propertySetFn;
122+
}
123+
}
128124
}

src/ServiceStack.Text/Common/WriteType.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ internal static class WriteType<T, TSerializer>
2727
internal static TypePropertyWriter[] PropertyWriters;
2828

2929
static WriteType()
30-
{
31-
CacheFn = Init() ? GetWriteFn() : null;
30+
{
31+
CacheFn = Init() ? GetWriteFn() : WriteEmptyType;
3232
}
3333

3434
public static WriteObjectDelegate Write
@@ -85,6 +85,11 @@ public TypePropertyWriter(string propertyName,
8585
}
8686
}
8787

88+
public static void WriteEmptyType(TextWriter writer, object value)
89+
{
90+
writer.Write(JsWriter.EmptyMap);
91+
}
92+
8893
public static void WriteProperties(TextWriter writer, object value)
8994
{
9095
if (typeof(TSerializer) == typeof(JsonTypeSerializer) && JsState.WritingKeyCount > 0)

0 commit comments

Comments
 (0)