11
11
//
12
12
using System ;
13
13
using System . Collections . Generic ;
14
+ using System . Linq ;
14
15
using System . Reflection ;
15
16
using System . Threading ;
16
17
using ServiceStack . Text ;
@@ -26,12 +27,16 @@ public static class StaticAccessors
26
27
27
28
public static Func < object , object > GetFastGetter ( this Type type , string propName )
28
29
{
29
- var key = $ " { type . Namespace } . { type . Name } :: { propName } " ;
30
+ var key = GetTypePropertyKey ( type , propName ) ;
30
31
Func < object , object > fn ;
31
32
if ( getterFnCache . TryGetValue ( key , out fn ) )
32
33
return fn ;
33
34
34
- fn = GetValueGetter ( type . GetPropertyInfo ( propName ) ) ;
35
+ var pi = type . GetPropertyInfo ( propName ) ;
36
+ if ( pi == null )
37
+ return null ;
38
+
39
+ fn = GetValueGetter ( pi ) ;
35
40
36
41
Dictionary < string , Func < object , object > > snapshot , newCache ;
37
42
do
@@ -45,16 +50,42 @@ public static Func<object, object> GetFastGetter(this Type type, string propName
45
50
return fn ;
46
51
}
47
52
53
+ private static string GetTypePropertyKey ( Type type , string propName )
54
+ {
55
+ var key = StringBuilderThreadStatic . Allocate ( )
56
+ . Append ( $ "{ type . Namespace } .{ type . Name } ::{ propName } ") ;
57
+
58
+ if ( type . IsGenericType ( ) )
59
+ {
60
+ key . Append ( "<" ) ;
61
+ var i = 0 ;
62
+ foreach ( var arg in type . GetGenericArguments ( ) )
63
+ {
64
+ if ( i ++ > 0 )
65
+ key . Append ( "," ) ;
66
+
67
+ key . Append ( $ "{ arg . Namespace } .{ arg . Name } ") ;
68
+ }
69
+ key . Append ( ">" ) ;
70
+ }
71
+
72
+ return StringBuilderThreadStatic . ReturnAndFree ( key ) ;
73
+ }
74
+
48
75
private static Dictionary < string , Action < object , object > > setterFnCache = new Dictionary < string , Action < object , object > > ( ) ;
49
76
50
77
public static Action < object , object > GetFastSetter ( this Type type , string propName )
51
78
{
52
- var key = $ " { type . Namespace } . { type . Name } :: { propName } " ;
79
+ var key = GetTypePropertyKey ( type , propName ) ;
53
80
Action < object , object > fn ;
54
81
if ( setterFnCache . TryGetValue ( key , out fn ) )
55
82
return fn ;
56
83
57
- fn = GetValueSetter ( type . GetPropertyInfo ( propName ) ) ;
84
+ var pi = type . GetPropertyInfo ( propName ) ;
85
+ if ( pi == null )
86
+ return null ;
87
+
88
+ fn = GetValueSetter ( pi ) ;
58
89
59
90
Dictionary < string , Action < object , object > > snapshot , newCache ;
60
91
do
@@ -86,7 +117,7 @@ public static Func<object, object> GetValueGetter(this PropertyInfo propertyInfo
86
117
#else
87
118
88
119
var instance = Expression . Parameter ( typeof ( object ) , "i" ) ;
89
- var convertInstance = Expression . TypeAs ( instance , propertyInfo . DeclaringType ) ;
120
+ var convertInstance = Expression . TypeAs ( instance , type ) ;
90
121
var property = Expression . Property ( convertInstance , propertyInfo ) ;
91
122
var convertProperty = Expression . TypeAs ( property , typeof ( object ) ) ;
92
123
return Expression . Lambda < Func < object , object > > ( convertProperty , instance ) . Compile ( ) ;
@@ -129,17 +160,17 @@ public static Func<T, object> GetValueGetter<T>(this FieldInfo fieldInfo)
129
160
}
130
161
131
162
#if ! XBOX
132
- public static Action < object , object > GetValueSetter ( this PropertyInfo propertyInfo , Type instanceType )
163
+ public static Action < object , object > GetValueSetter ( this PropertyInfo propertyInfo )
133
164
{
134
- return GetValueSetter ( propertyInfo ) ;
165
+ return GetValueSetter ( propertyInfo , propertyInfo . DeclaringType ) ;
135
166
}
136
167
137
- public static Action < object , object > GetValueSetter ( this PropertyInfo propertyInfo )
168
+ public static Action < object , object > GetValueSetter ( this PropertyInfo propertyInfo , Type instanceType )
138
169
{
139
170
var instance = Expression . Parameter ( typeof ( object ) , "i" ) ;
140
171
var argument = Expression . Parameter ( typeof ( object ) , "a" ) ;
141
172
142
- var type = ( Expression ) Expression . TypeAs ( instance , propertyInfo . DeclaringType ) ;
173
+ var type = ( Expression ) Expression . TypeAs ( instance , instanceType ) ;
143
174
144
175
var setterCall = Expression . Call (
145
176
type ,
0 commit comments