diff --git a/src/Umbraco.Core/Models/PreValue.cs b/src/Umbraco.Core/Models/PreValue.cs index 92cada007a..c33f642744 100644 --- a/src/Umbraco.Core/Models/PreValue.cs +++ b/src/Umbraco.Core/Models/PreValue.cs @@ -3,7 +3,7 @@ /// /// Represents a stored pre-value field value /// - public class PreValue + public class PreValue : IDeepCloneable { public PreValue(int id, string value) { @@ -25,5 +25,12 @@ /// The database id for the pre-value field value /// public int Id { get; private set; } + + public virtual object DeepClone() + { + //Memberwise clone on PreValue will work since it doesn't have any deep elements + var clone = (PreValue)MemberwiseClone(); + return clone; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PreValueCollection.cs b/src/Umbraco.Core/Models/PreValueCollection.cs index c6e07d6e34..e91aed8457 100644 --- a/src/Umbraco.Core/Models/PreValueCollection.cs +++ b/src/Umbraco.Core/Models/PreValueCollection.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Models /// Most legacy property editors won't support the dictionary format but new property editors should always use the dictionary format. /// In order to get overrideable pre-values working we need a dictionary since we'll have to reference a pre-value by a key. /// - public class PreValueCollection + public class PreValueCollection : IDeepCloneable { private IDictionary _preValuesAsDictionary; private IEnumerable _preValuesAsArray; @@ -82,5 +82,21 @@ namespace Umbraco.Core.Models } return result; } + + public object DeepClone() + { + var clone = (PreValueCollection) MemberwiseClone(); + if (_preValuesAsArray != null) + { + clone._preValuesAsArray = _preValuesAsArray.Select(x => (PreValue)x.DeepClone()).ToArray(); + } + if (_preValuesAsDictionary != null) + { + clone._preValuesAsDictionary = _preValuesAsDictionary.ToDictionary(x => x.Key, x => (PreValue)x.Value.DeepClone()); + } + + + return clone; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index 9484121ad7..0e8ae8c3bc 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -295,8 +295,8 @@ AND umbracoNode.id <> @id", var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeySearch(GetPrefixedCacheKey(dataTypeId)); if (cached != null && cached.Any()) { - //return from the cache - return cached.First(); + //return from the cache, ensure it's a cloned result + return (PreValueCollection)cached.First().DeepClone(); } l.UpgradeToWriteLock(); diff --git a/src/Umbraco.Tests/Models/PreValueCollectionTests.cs b/src/Umbraco.Tests/Models/PreValueCollectionTests.cs new file mode 100644 index 0000000000..49c9ab16bb --- /dev/null +++ b/src/Umbraco.Tests/Models/PreValueCollectionTests.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Models; + +namespace Umbraco.Tests.Models +{ + [TestFixture] + public class PreValueCollectionTests + { + [Test] + public void Can_Deep_Clone() + { + var d = new PreValueCollection(new Dictionary + { + {"blah1", new PreValue(1, "test1", 1)}, + {"blah2", new PreValue(2, "test1", 3)}, + {"blah3", new PreValue(3, "test1", 2)} + }); + + var a = new PreValueCollection(new[] + { + new PreValue(1, "test1", 1), + new PreValue(2, "test1", 3), + new PreValue(3, "test1", 2) + }); + + var clone1 = (PreValueCollection)d.DeepClone(); + var clone2 = (PreValueCollection)a.DeepClone(); + + Action assert = (orig, clone) => + { + Assert.AreNotSame(orig, clone); + var oDic = orig.FormatAsDictionary(); + var cDic = clone.FormatAsDictionary(); + Assert.AreEqual(oDic.Keys.Count(), cDic.Keys.Count()); + foreach (var k in oDic.Keys) + { + Assert.AreNotSame(oDic[k], cDic[k]); + Assert.AreEqual(oDic[k].Id, cDic[k].Id); + Assert.AreEqual(oDic[k].SortOrder, cDic[k].SortOrder); + Assert.AreEqual(oDic[k].Value, cDic[k].Value); + } + }; + + assert(d, clone1); + assert(a, clone2); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index a40f1a4688..6e56759ca5 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -173,6 +173,7 @@ +