From 68c4ce200847fb4d63fafa2da51991776546a62a Mon Sep 17 00:00:00 2001 From: Mole Date: Tue, 16 Mar 2021 14:18:17 +0100 Subject: [PATCH 1/5] Wrap calls to map in scopes --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 40 ++++++++++++++----- src/Umbraco.Tests/Mapping/MappingTests.cs | 37 +++++++++++++---- .../Testing/TestingTests/MockTests.cs | 18 ++++++++- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index e62825101c4f..fe58479335eb 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Exceptions; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Mapping { @@ -42,12 +43,17 @@ private readonly ConcurrentDictionary>> _maps = new ConcurrentDictionary>>(); + private readonly IScopeProvider _scopeProvider; + /// /// Initializes a new instance of the class. /// /// - public UmbracoMapper(MapDefinitionCollection profiles) + /// + public UmbracoMapper(MapDefinitionCollection profiles, IScopeProvider scopeProvider) { + _scopeProvider = scopeProvider; + foreach (var profile in profiles) profile.DefineMaps(this); } @@ -203,7 +209,10 @@ private TTarget Map(object source, Type sourceType, MapperContext conte if (ctor != null && map != null) { var target = ctor(source, context); - map(source, target, context); + using (var scope = _scopeProvider.CreateScope()) + { + map(source, target, context); + } return (TTarget)target; } @@ -248,11 +257,14 @@ private TTarget MapEnumerableInternal(IEnumerable source, Type targetGe { var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg)); - foreach (var sourceItem in source) + using (var scope = _scopeProvider.CreateScope()) { - var targetItem = ctor(sourceItem, context); - map(sourceItem, targetItem, context); - targetList.Add(targetItem); + foreach (var sourceItem in source) + { + var targetItem = ctor(sourceItem, context); + map(sourceItem, targetItem, context); + targetList.Add(targetItem); + } } object target = targetList; @@ -292,8 +304,15 @@ public TTarget Map(TSource source, TTarget target) public TTarget Map(TSource source, TTarget target, Action f) { var context = new MapperContext(this); - f(context); - return Map(source, target, context); + + TTarget targetInstance; + using (var scope = _scopeProvider.CreateScope()) + { + f(context); + targetInstance = Map(source, target, context); + } + + return targetInstance; } /// @@ -315,7 +334,10 @@ public TTarget Map(TSource source, TTarget target, MapperConte // if there is a direct map, map if (map != null) { - map(source, target, context); + using (var scope = _scopeProvider.CreateScope()) + { + map(source, target, context); + } return target; } diff --git a/src/Umbraco.Tests/Mapping/MappingTests.cs b/src/Umbraco.Tests/Mapping/MappingTests.cs index e6a382692c69..35f64cac62db 100644 --- a/src/Umbraco.Tests/Mapping/MappingTests.cs +++ b/src/Umbraco.Tests/Mapping/MappingTests.cs @@ -1,17 +1,40 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Threading; +using Moq; using NUnit.Framework; +using Umbraco.Core.Events; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Scoping; using Umbraco.Web.Models.ContentEditing; +using PropertyCollection = Umbraco.Core.Models.PropertyCollection; namespace Umbraco.Tests.Mapping { [TestFixture] public class MappingTests { + private IScopeProvider _scopeProvider; + + [SetUp] + public void MockScopeProvider() + { + var scopeMock = new Mock(); + scopeMock.Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of); + + _scopeProvider = scopeMock.Object; + } + [Test] public void SimpleMap() { @@ -19,7 +42,7 @@ public void SimpleMap() { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1 = new Thing1 { Value = "value" }; var thing2 = mapper.Map(thing1); @@ -44,7 +67,7 @@ public void EnumerableMap() { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1A = new Thing1 { Value = "valueA" }; var thing1B = new Thing1 { Value = "valueB" }; @@ -78,7 +101,7 @@ public void InheritedMap() { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing3 = new Thing3 { Value = "value" }; var thing2 = mapper.Map(thing3); @@ -103,7 +126,7 @@ public void CollectionsMap() { new MapperDefinition2(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // can map a PropertyCollection var source = new PropertyCollection(); @@ -119,7 +142,7 @@ public void ConcurrentMap() new MapperDefinition1(), new MapperDefinition3(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // the mapper currently has a map from Thing1 to Thing2 // because Thing3 inherits from Thing1, it will map a Thing3 instance, @@ -179,7 +202,7 @@ public void EnumMap() { new MapperDefinition4(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing5 = new Thing5() { @@ -203,7 +226,7 @@ public void NullPropertyMap() { new MapperDefinition5(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing7 = new Thing7(); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index f53b0bfff092..7eacccc8d5e2 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -1,4 +1,5 @@ using System; +using System.Data; using System.Globalization; using System.Linq; using System.Web.Security; @@ -9,11 +10,13 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; +using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; +using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; @@ -98,10 +101,21 @@ public void Can_Mock_UmbracoApiController_Dependencies_With_Injected_UmbracoMapp { var umbracoContext = TestObjects.GetUmbracoContextMock(); + var scopeProvider = new Mock(); + scopeProvider + .Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of); + var membershipHelper = new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var umbracoHelper = new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper); - var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() })); - + var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() }), scopeProvider.Object); + // ReSharper disable once UnusedVariable var umbracoApiController = new FakeUmbracoApiController(Mock.Of(), Mock.Of(), Mock.Of(), ServiceContext.CreatePartial(), AppCaches.NoCache, Mock.Of(), Mock.Of(), umbracoHelper, umbracoMapper); From 637e85ebbb50284e87fe91174dd8be4369a9be77 Mon Sep 17 00:00:00 2001 From: Mole Date: Tue, 16 Mar 2021 14:23:09 +0100 Subject: [PATCH 2/5] Autocomplete scopes --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index fe58479335eb..5800410e1601 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -209,7 +209,7 @@ private TTarget Map(object source, Type sourceType, MapperContext conte if (ctor != null && map != null) { var target = ctor(source, context); - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { map(source, target, context); } @@ -257,7 +257,7 @@ private TTarget MapEnumerableInternal(IEnumerable source, Type targetGe { var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg)); - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { foreach (var sourceItem in source) { @@ -306,7 +306,7 @@ public TTarget Map(TSource source, TTarget target, Action(TSource source, TTarget target, MapperConte // if there is a direct map, map if (map != null) { - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { map(source, target, context); } From aa6d046efef825f4ab41ef778a8f21f9a4712f1e Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 17 Mar 2021 09:43:36 +0100 Subject: [PATCH 3/5] Remove scope from method that calls another method that has a scope --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index 5800410e1601..ab9621406392 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -305,14 +305,8 @@ public TTarget Map(TSource source, TTarget target, Action From 3b83b7409ee2af1c21ec90507dae3d35a19a7a50 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 17 Mar 2021 10:08:08 +0100 Subject: [PATCH 4/5] Clean --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index ab9621406392..bd2f91652487 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -304,9 +304,8 @@ public TTarget Map(TSource source, TTarget target) public TTarget Map(TSource source, TTarget target, Action f) { var context = new MapperContext(this); - f(context); - return Map(source, target, context);; + return Map(source, target, context); } /// From 8b6fc762b5edb6af3c62b306265d788a0ed458e1 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 7 Apr 2021 13:54:42 +0200 Subject: [PATCH 5/5] Reintroduce old constructor to make non-breaking --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index bd2f91652487..36e3f9eab93b 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Scoping; @@ -58,6 +59,14 @@ public UmbracoMapper(MapDefinitionCollection profiles, IScopeProvider scopeProvi profile.DefineMaps(this); } + /// + /// Initializes a new instance of the class. + /// + /// + [Obsolete("This constructor is no longer used and will be removed in future versions, use the other constructor instead")] + public UmbracoMapper(MapDefinitionCollection profiles) : this(profiles, Current.ScopeProvider) + {} + #region Define private static TTarget ThrowCtor(TSource source, MapperContext context)