From 1fcf33bca0de2c7db23deea3b72527f4adf70636 Mon Sep 17 00:00:00 2001 From: DocSvartz Date: Tue, 7 Apr 2026 09:18:13 +0500 Subject: [PATCH] fix: #911- return in 7.4.0 behavior for types cannot be instantiated from itselves --- .../WhenMappingRecordRegression.cs | 17 +++++++++++++++++ src/Mapster/Adapters/ClassAdapter.cs | 2 +- src/Mapster/Adapters/NotSelfCreationAdapter.cs | 16 ++++++++++++++++ src/Mapster/Adapters/PrimitiveAdapter.cs | 2 +- src/Mapster/TypeAdapterConfig.cs | 5 +++-- src/Mapster/Utils/ReflectionUtils.cs | 13 +++++++++++++ 6 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/Mapster/Adapters/NotSelfCreationAdapter.cs diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs index 4a065274..94518641 100644 --- a/src/Mapster.Tests/WhenMappingRecordRegression.cs +++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs @@ -2,6 +2,7 @@ using Shouldly; using System; using System.Collections.Generic; +using System.Text.Json; using static Mapster.Tests.WhenExplicitMappingRequired; using static Mapster.Tests.WhenMappingDerived; @@ -522,6 +523,22 @@ public void ClassCtorActivateDefaultValue() }); } + /// + /// https://github.com/MapsterMapper/Mapster/issues/911 + /// + [TestMethod] + public void NotSelfCreationTypeMappingToSelfWithOutError() + { + var src = new Uri("https://www.google.com/"); + var srcJ = JsonDocument.Parse("{\"key\": \"value\"}"); + + var result = src.Adapt(); + var resultJ = srcJ.Adapt(); + + result.ToString().ShouldBe("https://www.google.com/"); + resultJ.RootElement.GetProperty("key").ToString().ShouldBe("value"); + } + #region NowNotWorking /// diff --git a/src/Mapster/Adapters/ClassAdapter.cs b/src/Mapster/Adapters/ClassAdapter.cs index a17b079a..03a2eb6b 100644 --- a/src/Mapster/Adapters/ClassAdapter.cs +++ b/src/Mapster/Adapters/ClassAdapter.cs @@ -16,7 +16,7 @@ namespace Mapster.Adapters /// internal class ClassAdapter : BaseClassAdapter { - protected override int Score => -150; + protected override int Score => -200; protected override bool CanMap(PreCompileArgument arg) { diff --git a/src/Mapster/Adapters/NotSelfCreationAdapter.cs b/src/Mapster/Adapters/NotSelfCreationAdapter.cs new file mode 100644 index 00000000..7079ec86 --- /dev/null +++ b/src/Mapster/Adapters/NotSelfCreationAdapter.cs @@ -0,0 +1,16 @@ +namespace Mapster.Adapters +{ + /// + /// Immitation behavior in 7.4.0 for Types that cannot be instantiated from itselves + /// Example: Uri, JsonDocument + /// + internal class NotSelfCreationAdapter : PrimitiveAdapter + { + protected override int Score => -150; + + protected override bool CanMap(PreCompileArgument arg) + { + return !arg.ExplicitMapping && arg.SourceType == arg.DestinationType && arg.DestinationType.IsNotSelfCreation(); + } + } +} diff --git a/src/Mapster/Adapters/PrimitiveAdapter.cs b/src/Mapster/Adapters/PrimitiveAdapter.cs index c2d411db..622f32b1 100644 --- a/src/Mapster/Adapters/PrimitiveAdapter.cs +++ b/src/Mapster/Adapters/PrimitiveAdapter.cs @@ -9,7 +9,7 @@ namespace Mapster.Adapters { internal class PrimitiveAdapter : BaseAdapter { - protected override int Score => -200; //must do last + protected override int Score => -210; //must do last protected override bool CanMap(PreCompileArgument arg) { diff --git a/src/Mapster/TypeAdapterConfig.cs b/src/Mapster/TypeAdapterConfig.cs index 1e6abade..34f22495 100644 --- a/src/Mapster/TypeAdapterConfig.cs +++ b/src/Mapster/TypeAdapterConfig.cs @@ -20,8 +20,9 @@ private static List CreateRuleTemplate() { return new List { - new PrimitiveAdapter().CreateRule(), //-200 - new ClassAdapter().CreateRule(), //-150 + new PrimitiveAdapter().CreateRule(), //-210 + new ClassAdapter().CreateRule(), //-200 + new NotSelfCreationAdapter().CreateRule(), //-150 new RecordTypeAdapter().CreateRule(), //-149 new ReadOnlyInterfaceAdapter().CreateRule(), // -148 new CollectionAdapter().CreateRule(), //-125 diff --git a/src/Mapster/Utils/ReflectionUtils.cs b/src/Mapster/Utils/ReflectionUtils.cs index 505166eb..a010984a 100644 --- a/src/Mapster/Utils/ReflectionUtils.cs +++ b/src/Mapster/Utils/ReflectionUtils.cs @@ -453,5 +453,18 @@ public static bool IsMapsterImmutable(this Type type) { return type.IsMapsterPrimitive() || type.IsRecordType(); } + + public static bool IsNotSelfCreation(this Type type) + { + if (type.IsMapsterPrimitive()) + return false; + if(type.IsCollectionCompatible()) + return false; + + if (type == typeof(Type) || type.BaseType == typeof(MulticastDelegate)) + return true; + + return type.GetFieldsAndProperties().Any(it => (it.SetterModifier & (AccessModifier.Public | AccessModifier.NonPublic)) == 0); + } } }