Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 7d278a1

Browse files
committed
Add GetFastGetter/Setter for property accessor
1 parent 5b8e621 commit 7d278a1

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/ServiceStack.Text/AssemblyUtils.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ public static Type FindType(string typeName)
4545
do
4646
{
4747
snapshot = TypeCache;
48-
newCache = new Dictionary<string, Type>(TypeCache);
49-
newCache[typeName] = type;
48+
newCache = new Dictionary<string, Type>(TypeCache) { [typeName] = type };
5049

5150
} while (!ReferenceEquals(
5251
Interlocked.CompareExchange(ref TypeCache, newCache, snapshot), snapshot));

src/ServiceStack.Text/Reflection/StaticAccessors.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
// Licensed under the same terms of ServiceStack.
1111
//
1212
using System;
13+
using System.Collections.Generic;
1314
using System.Reflection;
15+
using System.Threading;
1416
using ServiceStack.Text;
1517
#if !XBOX
1618
using System.Linq.Expressions;
@@ -20,6 +22,52 @@ namespace ServiceStack.Reflection
2022
//Also exists in ServiceStack.Common in ServiceStack.Reflection namespace
2123
public static class StaticAccessors
2224
{
25+
private static Dictionary<string, Func<object, object>> getterFnCache = new Dictionary<string, Func<object, object>>();
26+
27+
public static Func<object, object> GetFastGetter(this Type type, string propName)
28+
{
29+
var key = $"{type.Namespace}.{type.Name}::{propName}";
30+
Func<object, object> fn;
31+
if (getterFnCache.TryGetValue(key, out fn))
32+
return fn;
33+
34+
fn = GetValueGetter(type.GetProperty(propName));
35+
36+
Dictionary<string, Func<object, object>> snapshot, newCache;
37+
do
38+
{
39+
snapshot = getterFnCache;
40+
newCache = new Dictionary<string, Func<object, object>>(getterFnCache) { [key] = fn };
41+
42+
} while (!ReferenceEquals(
43+
Interlocked.CompareExchange(ref getterFnCache, newCache, snapshot), snapshot));
44+
45+
return fn;
46+
}
47+
48+
private static Dictionary<string, Action<object, object>> setterFnCache = new Dictionary<string, Action<object, object>>();
49+
50+
public static Action<object, object> GetFastSetter(this Type type, string propName)
51+
{
52+
var key = $"{type.Namespace}.{type.Name}::{propName}";
53+
Action<object, object> fn;
54+
if (setterFnCache.TryGetValue(key, out fn))
55+
return fn;
56+
57+
fn = GetValueSetter(type.GetProperty(propName));
58+
59+
Dictionary<string, Action<object, object>> snapshot, newCache;
60+
do
61+
{
62+
snapshot = setterFnCache;
63+
newCache = new Dictionary<string, Action<object, object>>(setterFnCache) { [key] = fn };
64+
65+
} while (!ReferenceEquals(
66+
Interlocked.CompareExchange(ref setterFnCache, newCache, snapshot), snapshot));
67+
68+
return fn;
69+
}
70+
2371
public static Func<object, object> GetValueGetter(this PropertyInfo propertyInfo)
2472
{
2573
return GetValueGetter(propertyInfo, propertyInfo.DeclaringType);

0 commit comments

Comments
 (0)