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

Commit ccf34dc

Browse files
committed
Add GetCachedGenericType() for caching generic typed created with MakeGenericType
1 parent 56991c0 commit ccf34dc

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

src/ServiceStack.Text/ReflectionExtensions.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Collections.Generic;
1616
using System.ComponentModel;
1717
using System.Linq;
18+
using System.Linq.Expressions;
1819
using System.Reflection;
1920
using System.Runtime.Serialization;
2021
using System.Threading;
@@ -1793,6 +1794,42 @@ public static Type GetCollectionType(this Type type)
17931794
return type.ElementType() ?? type.GetTypeGenericArguments().FirstOrDefault();
17941795
}
17951796

1797+
static Dictionary<string, Type> GenericTypeCache = new Dictionary<string, Type>();
1798+
1799+
public static Type GetCachedGenericType(this Type type, Type[] argTypes)
1800+
{
1801+
if (!type.IsGenericTypeDefinition)
1802+
throw new ArgumentException(type.FullName + " is not a Generic Type Definition");
1803+
1804+
var sb = StringBuilderThreadStatic.Allocate()
1805+
.Append(type.FullName);
1806+
foreach (var argType in argTypes)
1807+
{
1808+
sb.Append('|')
1809+
.Append(argType.FullName);
1810+
}
1811+
1812+
var key = StringBuilderThreadStatic.ReturnAndFree(sb);
1813+
1814+
Type genericType;
1815+
if (GenericTypeCache.TryGetValue(key, out genericType))
1816+
return genericType;
1817+
1818+
genericType = type.MakeGenericType(argTypes);
1819+
1820+
Dictionary<string, Type> snapshot, newCache;
1821+
do
1822+
{
1823+
snapshot = GenericTypeCache;
1824+
newCache = new Dictionary<string, Type>(GenericTypeCache);
1825+
newCache[key] = genericType;
1826+
1827+
} while (!ReferenceEquals(
1828+
Interlocked.CompareExchange(ref GenericTypeCache, newCache, snapshot), snapshot));
1829+
1830+
return genericType;
1831+
}
1832+
17961833
private static readonly ConcurrentDictionary<Type, ObjectDictionaryDefinition> toObjectMapCache =
17971834
new ConcurrentDictionary<Type, ObjectDictionaryDefinition>();
17981835

@@ -1903,6 +1940,11 @@ public static object FromObjectDictionary(this Dictionary<string, object> values
19031940
return to;
19041941
}
19051942

1943+
public static object FromObjectDictionary<T>(this Dictionary<string, object> values)
1944+
{
1945+
return values.FromObjectDictionary(typeof(T));
1946+
}
1947+
19061948
private static ObjectDictionaryDefinition CreateObjectDictionaryDefinition(Type type)
19071949
{
19081950
var def = new ObjectDictionaryDefinition

0 commit comments

Comments
 (0)