diff --git a/src/Mapster.Tests/WhenIgnoreMapping.cs b/src/Mapster.Tests/WhenIgnoreMapping.cs
index 585e911c..245c4e63 100644
--- a/src/Mapster.Tests/WhenIgnoreMapping.cs
+++ b/src/Mapster.Tests/WhenIgnoreMapping.cs
@@ -1,4 +1,6 @@
using System;
+using System.Linq;
+using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Shouldly;
@@ -55,6 +57,109 @@ public void TestIgnoreMember()
poco2.Name.ShouldBeNull();
}
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/707
+ ///
+ [TestMethod]
+ public void WhenClassIgnoreCtorParamGetDefaultValue()
+ {
+ var config = new TypeAdapterConfig()
+ {
+ RequireDestinationMemberSource = true,
+ };
+ config.Default
+ .NameMatchingStrategy(new NameMatchingStrategy
+ {
+ SourceMemberNameConverter = input => input.ToLowerInvariant(),
+ DestinationMemberNameConverter = input => input.ToLowerInvariant(),
+ })
+ ;
+ config
+ .NewConfig()
+ .MapToConstructor(GetConstructor())
+ .Ignore(e => e.Id);
+
+ var source = new A707 { Text = "test" };
+ var dest = new B707(123, "Hello");
+
+ var docKind = source.Adapt(config);
+ var mapTotarget = source.Adapt(dest,config);
+
+ docKind.Id.ShouldBe(0);
+ mapTotarget.Id.ShouldBe(123);
+ mapTotarget.Text.ShouldBe("test");
+ }
+
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/723
+ ///
+ [TestMethod]
+ public void MappingToIntefaceWithIgnorePrivateSetProperty()
+ {
+ TypeAdapterConfig
+ .NewConfig()
+ .TwoWays()
+ .Ignore(dest => dest.Ignore);
+
+ InterfaceDestination723 dataDestination = new Data723() { Inter = "IterDataDestination", Ignore = "IgnoreDataDestination" };
+
+ Should.NotThrow(() =>
+ {
+ var isourse = dataDestination.Adapt();
+ var idestination = dataDestination.Adapt();
+ });
+
+ }
+
+ #region TestClasses
+
+ public interface InterfaceDestination723
+ {
+ public string Inter { get; set; }
+ public string Ignore { get; }
+ }
+
+ public interface InterfaceSource723
+ {
+ public string Inter { get; set; }
+ }
+
+ private class Data723 : InterfaceSource723, InterfaceDestination723
+ {
+ public string Ignore { get; set; }
+
+ public string Inter { get; set; }
+ }
+
+ static ConstructorInfo? GetConstructor()
+ {
+ var parameterlessCtorInfo = typeof(TDestination).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, new Type[0]);
+
+ var ctors = typeof(TDestination).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+ var validCandidateCtors = ctors.Except(new[] { parameterlessCtorInfo }).ToArray();
+ var ctorToUse = validCandidateCtors.Length == 1
+ ? validCandidateCtors.First()
+ : validCandidateCtors.OrderByDescending(c => c.GetParameters().Length).First();
+
+ return ctorToUse;
+ }
+ public class A707
+ {
+ public string? Text { get; set; }
+ }
+
+ public class B707
+ {
+ public int Id { get; private set; }
+ public string Text { get; private set; }
+
+ public B707(int id, string text)
+ {
+ Id = id;
+ Text = text;
+ }
+ }
+
public class Poco
{
public Guid Id { get; set; }
@@ -67,5 +172,7 @@ public class Dto
[JsonIgnore]
public string Name { get; set; }
}
+
+ #endregion TestClasses
}
}
diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs
index e5d719e4..f4658e85 100644
--- a/src/Mapster.Tests/WhenMappingRecordRegression.cs
+++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs
@@ -353,6 +353,25 @@ public void MappingInterfaceToInterface()
}
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/456
+ ///
+ [TestMethod]
+ public void WhenRecordReceivedIgnoreCtorParamProcessing()
+ {
+ TypeAdapterConfig.NewConfig()
+ .Ignore(dest => dest.Name);
+
+ var userDto = new UserDto456("Amichai");
+ var user = new UserRecord456("John");
+
+ var map = userDto.Adapt();
+ var maptoTarget = userDto.Adapt(user);
+
+ map.Name.ShouldBeNullOrEmpty();
+ maptoTarget.Name.ShouldBe("John");
+ }
+
#region NowNotWorking
@@ -382,6 +401,11 @@ public void CollectionUpdate()
#region TestClasses
+
+ public record UserRecord456(string Name);
+
+ public record UserDto456(string Name);
+
public interface IActivityDataExtentions : IActivityData
{
public int TempLength { get; set; }
diff --git a/src/Mapster/Adapters/BaseClassAdapter.cs b/src/Mapster/Adapters/BaseClassAdapter.cs
index faa490ec..966f2fe9 100644
--- a/src/Mapster/Adapters/BaseClassAdapter.cs
+++ b/src/Mapster/Adapters/BaseClassAdapter.cs
@@ -15,7 +15,7 @@ internal abstract class BaseClassAdapter : BaseAdapter
#region Build the Adapter Model
- protected ClassMapping CreateClassConverter(Expression source, ClassModel classModel, CompileArgument arg, Expression? destination = null)
+ protected ClassMapping CreateClassConverter(Expression source, ClassModel classModel, CompileArgument arg, Expression? destination = null, bool ctorMapping = false)
{
var destinationMembers = classModel.Members;
var unmappedDestinationMembers = new List();
@@ -29,7 +29,7 @@ src is LambdaExpression lambda
: ExpressionEx.PropertyOrFieldPath(source, (string)src)));
foreach (var destinationMember in destinationMembers)
{
- if (ProcessIgnores(arg, destinationMember, out var ignore))
+ if (ProcessIgnores(arg, destinationMember, out var ignore) && !ctorMapping)
continue;
var resolvers = arg.Settings.ValueAccessingStrategies.AsEnumerable();
@@ -80,7 +80,8 @@ select fn(src, destinationMember, arg))
{
if (classModel.BreakOnUnmatched)
return null!;
- unmappedDestinationMembers.Add(destinationMember.Name);
+ if(!arg.Settings.Ignore.Any(x=>x.Key == destinationMember.Name)) // Don't mark a constructor parameter if it was explicitly ignored
+ unmappedDestinationMembers.Add(destinationMember.Name);
}
properties.Add(propertyModel);
@@ -128,7 +129,7 @@ protected static bool ProcessIgnores(
&& ignore.Condition == null;
}
- protected Expression CreateInstantiationExpression(Expression source, ClassMapping classConverter, CompileArgument arg)
+ protected Expression CreateInstantiationExpression(Expression source, ClassMapping classConverter, CompileArgument arg, Expression? destination)
{
var members = classConverter.Members;
@@ -156,6 +157,20 @@ protected Expression CreateInstantiationExpression(Expression source, ClassMappi
var condition = ExpressionEx.Not(body);
getter = Expression.Condition(condition, getter, defaultConst);
}
+ else
+ if (arg.Settings.Ignore.Any(x => x.Key == member.DestinationMember.Name))
+ {
+ getter = defaultConst;
+
+ if (arg.MapType == MapType.MapToTarget && arg.DestinationType.IsRecordType())
+ {
+ var find = arg.DestinationType.GetFieldsAndProperties(arg.Settings.EnableNonPublicMembers.GetValueOrDefault()).ToArray()
+ .Where(x => x.Name == member.DestinationMember.Name).FirstOrDefault();
+
+ if (find != null)
+ getter = Expression.MakeMemberAccess(destination, (MemberInfo)find.Info);
+ }
+ }
}
arguments.Add(getter);
}
diff --git a/src/Mapster/Adapters/ClassAdapter.cs b/src/Mapster/Adapters/ClassAdapter.cs
index 407c5a5b..6ae450fa 100644
--- a/src/Mapster/Adapters/ClassAdapter.cs
+++ b/src/Mapster/Adapters/ClassAdapter.cs
@@ -69,19 +69,19 @@ protected override Expression CreateInstantiationExpression(Expression source, E
classConverter = destType.GetConstructors()
.OrderByDescending(it => it.GetParameters().Length)
.Select(it => GetConstructorModel(it, true))
- .Select(it => CreateClassConverter(source, it, arg))
+ .Select(it => CreateClassConverter(source, it, arg, ctorMapping:true))
.FirstOrDefault(it => it != null);
}
else
{
var model = GetConstructorModel(ctor, false);
- classConverter = CreateClassConverter(source, model, arg);
+ classConverter = CreateClassConverter(source, model, arg, ctorMapping:true);
}
if (classConverter == null)
return base.CreateInstantiationExpression(source, destination, arg);
- return CreateInstantiationExpression(source, classConverter, arg);
+ return CreateInstantiationExpression(source, classConverter, arg, destination);
}
protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
diff --git a/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs b/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs
index 3703c281..ea4aa6e1 100644
--- a/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs
+++ b/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs
@@ -38,8 +38,8 @@ protected override Expression CreateInstantiationExpression(Expression source, E
return base.CreateInstantiationExpression(source, destination, arg);
var ctor = destType.GetConstructors()[0];
var classModel = GetConstructorModel(ctor, false);
- var classConverter = CreateClassConverter(source, classModel, arg);
- return CreateInstantiationExpression(source, classConverter, arg);
+ var classConverter = CreateClassConverter(source, classModel, arg, ctorMapping:true);
+ return CreateInstantiationExpression(source, classConverter, arg, destination);
}
else
return base.CreateInstantiationExpression(source,destination, arg);
diff --git a/src/Mapster/Adapters/RecordTypeAdapter.cs b/src/Mapster/Adapters/RecordTypeAdapter.cs
index 009af932..0ef0532d 100644
--- a/src/Mapster/Adapters/RecordTypeAdapter.cs
+++ b/src/Mapster/Adapters/RecordTypeAdapter.cs
@@ -31,8 +31,8 @@ protected override Expression CreateInstantiationExpression(Expression source, E
var ctor = destType.GetConstructors()
.OrderByDescending(it => it.GetParameters().Length).ToArray().FirstOrDefault(); // Will be used public constructor with the maximum number of parameters
var classModel = GetConstructorModel(ctor, false);
- var classConverter = CreateClassConverter(source, classModel, arg);
- var installExpr = CreateInstantiationExpression(source, classConverter, arg);
+ var classConverter = CreateClassConverter(source, classModel, arg, ctorMapping:true);
+ var installExpr = CreateInstantiationExpression(source, classConverter, arg, destination);
return RecordInlineExpression(source, arg, installExpr); // Activator field when not include in public ctor
}