From a7c089bf01a9f23bf8309c1883146601c8c3e610 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 4 Jan 2013 01:45:06 +0300 Subject: [PATCH] Fixes: #U4-814 - DynamicNode now has proper instance level caching for returning properties and children. --- .../RazorDynamicNode/DynamicNode.cs | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs index 4fc8b76db6..79f6f69c51 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Dynamic; using System.Linq; @@ -45,6 +46,9 @@ namespace umbraco.MacroEngines //private readonly Guid DATATYPE_INTEGER_GUID = new Guid("1413afcb-d19a-4173-8e9a-68288d2a73b8"); #endregion + private DynamicNodeList _cachedChildren; + private readonly ConcurrentDictionary _cachedMemberOutput = new ConcurrentDictionary(); + internal readonly DynamicBackingItem n; public DynamicNodeList ownerList; @@ -154,13 +158,20 @@ namespace umbraco.MacroEngines { get { - List children = n.ChildrenAsList; - //testing - if (children.Count == 0 && n.Id == 0) - { - return new DynamicNodeList(new List { this.n }); - } - return new DynamicNodeList(n.ChildrenAsList); + if (_cachedChildren == null) + { + List children = n.ChildrenAsList; + //testing + if (children.Count == 0 && n.Id == 0) + { + _cachedChildren = new DynamicNodeList(new List {this.n}); + } + else + { + _cachedChildren = new DynamicNodeList(n.ChildrenAsList); + } + } + return _cachedChildren; } } public DynamicNodeList XPath(string xPath) @@ -470,13 +481,21 @@ namespace umbraco.MacroEngines public override bool TryGetMember(GetMemberBinder binder, out object result) { + var name = binder.Name; + + //check the cache first! + if (_cachedMemberOutput.TryGetValue(name, out result)) + { + return true; + } - var name = binder.Name; result = null; //this will never be returned if (name == "ChildrenAsList" || name == "Children") { result = GetChildrenAsList; + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); return true; } bool propertyExists = false; @@ -524,6 +543,8 @@ namespace umbraco.MacroEngines if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance)) { result = instance; + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); return true; } else @@ -547,6 +568,8 @@ namespace umbraco.MacroEngines if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance)) { result = instance; + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); return true; } else @@ -561,8 +584,10 @@ namespace umbraco.MacroEngines } //convert the string value to a known type - return ConvertPropertyValueByDataType(ref result, name, dataType); - + var returnVal = ConvertPropertyValueByDataType(ref result, name, dataType); + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); + return returnVal; } //check if the alias is that of a child type @@ -577,6 +602,8 @@ namespace umbraco.MacroEngines if (filteredTypeChildren.Any()) { result = new DynamicNodeList(filteredTypeChildren); + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); return true; } @@ -591,6 +618,8 @@ namespace umbraco.MacroEngines null, n, null); + //cache the result so we don't have to re-process the whole thing + _cachedMemberOutput.TryAdd(name, result); return true; } catch