Skip to content

Commit 774f201

Browse files
committed
Adds a simple cache mechanism to hold reflected property info when cloning - reduces perf to 10% of what it used to be
1 parent 12e2aa6 commit 774f201

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/Umbraco.Core/Models/DeepCloneHelper.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections;
3+
using System.Collections.Concurrent;
34
using System.Collections.Generic;
45
using System.Linq;
56
using System.Reflection;
@@ -27,6 +28,11 @@ internal class DoNotCloneAttribute : Attribute
2728

2829
public static class DeepCloneHelper
2930
{
31+
/// <summary>
32+
/// Used to avoid constant reflection (perf)
33+
/// </summary>
34+
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropCache = new ConcurrentDictionary<Type, PropertyInfo[]>();
35+
3036
/// <summary>
3137
/// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output')
3238
/// </summary>
@@ -43,16 +49,18 @@ public static void DeepCloneRefProperties(IDeepCloneable input, IDeepCloneable o
4349
throw new InvalidOperationException("Both the input and output types must be the same");
4450
}
4551

46-
var refProperties = inputType.GetProperties()
47-
.Where(x =>
48-
//is not attributed with the ignore clone attribute
52+
var refProperties = PropCache.GetOrAdd(inputType, type =>
53+
inputType.GetProperties()
54+
.Where(x =>
55+
//is not attributed with the ignore clone attribute
4956
Attribute.GetCustomAttribute(x, typeof(DoNotCloneAttribute)) == null
50-
//reference type but not string
51-
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
52-
//settable
53-
&& x.CanWrite
54-
//non-indexed
55-
&& x.GetIndexParameters().Any() == false);
57+
//reference type but not string
58+
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
59+
//settable
60+
&& x.CanWrite
61+
//non-indexed
62+
&& x.GetIndexParameters().Any() == false)
63+
.ToArray());
5664

5765
foreach (var propertyInfo in refProperties)
5866
{

0 commit comments

Comments
 (0)