diff --git a/src/Mapster.Tests/WhenExplicitMappingRequired.cs b/src/Mapster.Tests/WhenExplicitMappingRequired.cs index b5d89492..25b43474 100644 --- a/src/Mapster.Tests/WhenExplicitMappingRequired.cs +++ b/src/Mapster.Tests/WhenExplicitMappingRequired.cs @@ -13,6 +13,7 @@ public class WhenExplicitMappingRequired public void TestCleanup() { TypeAdapterConfig.GlobalSettings.RequireExplicitMapping = false; + TypeAdapterConfig.GlobalSettings.RequireExplicitMappingPrimitive = false; TypeAdapterConfig.GlobalSettings.Clear(); } @@ -140,8 +141,60 @@ public void UnmappedChildPocoShouldFailed() setter.Compile(); // Should fail here } + [TestMethod] + public void RequireExplicitMappingPrimitiveWork() + { + TypeAdapterConfig.GlobalSettings.RequireExplicitMappingPrimitive = true; + + TypeAdapterConfig.NewConfig(); + + Should.Throw(() => + { + TypeAdapterConfig.GlobalSettings.Compile(); // throw CompileException + }); + + byte byteSource = 10; + + byteSource.Adapt(); // Should work when the type is mapped to itself + + Should.Throw(() => + { + byteSource.Adapt(); // throw CompileException, Do not map to another primitive type without registering the configuration + }); + + Should.NotThrow(() => + { + TypeAdapterConfig.NewConfig(); + + byteSource.Adapt(); // Not throw CompileException when config is registering + }); + + Should.NotThrow(() => + { + TypeAdapterConfig.NewConfig() + .Map(dest=> dest.MyProperty, src=> int.Parse(src.MyProperty)); + // it work works because int.Parse return Type Int. Type is mapped to itself (int -> int) without config. + + var sourceMapconfig = new Source783() { MyProperty = "128" }; + var resultMapconfig = sourceMapconfig.Adapt(); + + resultMapconfig.MyProperty.ShouldBe(128); + }); + + } + + #region TestClasses + + public class Source783 + { + public string MyProperty { get; set; } = ""; + } + public class Destination783 + { + public int MyProperty { get; set; } + } public enum NameEnum { diff --git a/src/Mapster/Adapters/PrimitiveAdapter.cs b/src/Mapster/Adapters/PrimitiveAdapter.cs index cfc7c809..ca8c861c 100644 --- a/src/Mapster/Adapters/PrimitiveAdapter.cs +++ b/src/Mapster/Adapters/PrimitiveAdapter.cs @@ -18,6 +18,8 @@ protected override bool CanMap(PreCompileArgument arg) protected override Expression CreateExpressionBody(Expression source, Expression? destination, CompileArgument arg) { + if (arg.SourceType != arg.DestinationType && arg.Context.Config.RequireExplicitMappingPrimitive && !arg.ExplicitMapping) + throw new InvalidOperationException("Implicit mapping is not allowed (check GlobalSettings.RequireExplicitMapping) and no configuration exists"); if (arg.Settings.MapToTargetPrimitive == true) { diff --git a/src/Mapster/TypeAdapterConfig.cs b/src/Mapster/TypeAdapterConfig.cs index cb8ac881..5056bd42 100644 --- a/src/Mapster/TypeAdapterConfig.cs +++ b/src/Mapster/TypeAdapterConfig.cs @@ -82,6 +82,7 @@ private static List CreateRuleTemplate() public bool RequireDestinationMemberSource { get; set; } public bool RequireExplicitMapping { get; set; } + public bool RequireExplicitMappingPrimitive { get; set; } public bool AllowImplicitDestinationInheritance { get; set; } public bool AllowImplicitSourceInheritance { get; set; } = true; public bool SelfContainedCodeGeneration { get; set; } @@ -495,7 +496,7 @@ private LambdaExpression CreateMapInvokeExpression(Type sourceType, Type destina internal Expression CreateMapInvokeExpressionBody(Type sourceType, Type destinationType, Expression p) { - if (RequireExplicitMapping) + if (RequireExplicitMapping || RequireExplicitMappingPrimitive) { var key = new TypeTuple(sourceType, destinationType); _mapDict[key] = Compiler(CreateMapExpression(key, MapType.Map)); @@ -518,7 +519,7 @@ internal Expression CreateMapInvokeExpressionBody(Type sourceType, Type destinat internal Expression CreateMapToTargetInvokeExpressionBody(Type sourceType, Type destinationType, Expression p1, Expression p2) { - if (RequireExplicitMapping) + if (RequireExplicitMapping || RequireExplicitMappingPrimitive) { var key = new TypeTuple(sourceType, destinationType); _mapToTargetDict[key] = Compiler(CreateMapExpression(key, MapType.MapToTarget));