From 93a2d3fe65814b7101b07cdf4c7b7947a892ef2c Mon Sep 17 00:00:00 2001 From: DocSvartz Date: Fri, 10 Jan 2025 07:04:24 +0500 Subject: [PATCH 1/2] Fix issue #755 - revert to behavior from 7.4.0 --- .../WhenMappingRecordRegression.cs | 184 ++++++++++++++++++ .../Adapters/ReadOnlyInterfaceAdapter.cs | 20 ++ 2 files changed, 204 insertions(+) diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs index f68cd6f9..534eb2dd 100644 --- a/src/Mapster.Tests/WhenMappingRecordRegression.cs +++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs @@ -278,6 +278,83 @@ public void MultiCtorAndInlineRecordWorked() } + [TestMethod] + public void MappingInterfaceToInterface() + { + TypeAdapterConfig + .ForType() + .Map(dest => dest.TempLength, src => src.Temp.Length); + + + var sourceBase = new SampleInterfaceClsBase + { + ActivityData = new SampleActivityData + { + Data = new SampleActivityParsedData + { + Steps = new List { "A", "B", "C" } + }, + Temp = "Temp data" + + } + + }; + var sourceDerived = new SampleInterfaceClsDerived + { + ActivityData = new SampleActivityData + { + Data = new SampleActivityParsedData + { + Steps = new List { "X", "Y", "Z" } + }, + Temp = "Update Temp data" + + } + + }; + + var sourceExt = new SampleInterfaceClsExtentions + { + ActivityData = new SampleActivityDataExtentions + { + Data = new SampleActivityParsedData + { + Steps = new List { "o", "o", "o" } + }, + Temp = "Extentions data", + TempLength = "Extentions data".Length + + } + + }; + + var TargetBase = sourceBase.Adapt(); + var targetDerived = sourceDerived.Adapt(); + var update = targetDerived.Adapt(TargetBase); + + var targetExtention = sourceExt.Adapt(); + + + var updExt = targetDerived.Adapt(targetExtention); + + targetDerived.ShouldNotBeNull(); + targetDerived.ShouldSatisfyAllConditions( + () => targetDerived.ActivityData.ShouldBe(sourceDerived.ActivityData), + () => update.ActivityData.ShouldBe(targetDerived.ActivityData), + + ()=> updExt.ActivityData.ShouldBe(targetExtention.ActivityData), + () => ((SampleActivityDataExtentions)updExt.ActivityData).Temp.ShouldBe(sourceDerived.ActivityData.Temp), + () => ((SampleActivityDataExtentions)updExt.ActivityData).TempLength.ShouldBe(sourceDerived.ActivityData.Temp.Length), + // All implementations of the IActivityData interface do not provide access to the Data property for all implementations of the SampleActivityData class, + // so this property will not be changed by mapping + () => ((SampleActivityDataExtentions)updExt.ActivityData).Data.ShouldBe(((SampleActivityDataExtentions)targetExtention.ActivityData).Data) + + ); + + } + + + #region NowNotWorking /// @@ -305,6 +382,104 @@ public void CollectionUpdate() #region TestClasses + public interface IActivityDataExtentions : IActivityData + { + public int TempLength { get; set; } + } + + public interface IActivityData : IActivityDataBase + { + public string Temp { get; set; } + } + + public interface IActivityDataBase + { + + } + + + public class SampleInterfaceClsExtentions + { + public IActivityDataExtentions? ActivityData { get; set; } + + public SampleInterfaceClsExtentions() + { + + } + + public SampleInterfaceClsExtentions(IActivityDataExtentions data) + { + SetActivityData(data); + } + + public void SetActivityData(IActivityDataExtentions data) + { + ActivityData = data; + } + } + + + + public class SampleInterfaceClsBase + { + public IActivityDataBase? ActivityData { get; set; } + + public SampleInterfaceClsBase() + { + + } + + public SampleInterfaceClsBase(IActivityDataBase data) + { + SetActivityData(data); + } + + public void SetActivityData(IActivityDataBase data) + { + ActivityData = data; + } + } + + public class SampleInterfaceClsDerived + { + public IActivityData? ActivityData { get; set; } + + public SampleInterfaceClsDerived() + { + + } + + public SampleInterfaceClsDerived(IActivityData data) + { + SetActivityData(data); + } + + public void SetActivityData(IActivityData data) + { + ActivityData = data; + } + } + + public class SampleActivityDataExtentions : IActivityDataExtentions + { + public SampleActivityParsedData Data { get; set; } + public string Temp { get; set; } + public int TempLength { get; set; } + } + + public class SampleActivityData : IActivityData + { + public SampleActivityParsedData Data { get; set; } + public string Temp { get; set; } + } + + public class SampleActivityParsedData + { + public List Steps { get; set; } = new List(); + } + + + class MultiCtorAndInlinePoco { public int MyInt { get; set; } @@ -499,5 +674,14 @@ sealed record TestSealedRecord() sealed record TestSealedRecordPositional(int X); + + + + + + + + + #endregion TestClasses } diff --git a/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs b/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs index df4a0f66..f81a1f74 100644 --- a/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs +++ b/src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs @@ -11,6 +11,7 @@ internal class ReadOnlyInterfaceAdapter : ClassAdapter protected override bool CanMap(PreCompileArgument arg) { return arg.DestinationType.IsInterface; + } protected override bool CanInline(Expression source, Expression? destination, CompileArgument arg) @@ -45,5 +46,24 @@ protected override Expression CreateInstantiationExpression(Expression source, E return base.CreateInstantiationExpression(source,destination, arg); } + protected override Expression CreateExpressionBody(Expression source, Expression? destination, CompileArgument arg) + { + if (source.Type.IsInterface) + { + if (!arg.DestinationType.IsAssignableFrom(arg.SourceType)) + return base.CreateExpressionBody(source, destination, arg); + + if (arg.MapType != MapType.MapToTarget) + return Expression.Convert(source, arg.DestinationType); + + if (arg.MapType == MapType.MapToTarget) + return source; + + return base.CreateExpressionBody(source, destination, arg); + } + + return base.CreateExpressionBody(source, destination, arg); + } + } } From 424134258b330b5cb9484d098944c314dd58b893 Mon Sep 17 00:00:00 2001 From: DocSvartz Date: Sat, 11 Jan 2025 21:34:17 +0500 Subject: [PATCH 2/2] fix comment --- src/Mapster.Tests/WhenMappingRecordRegression.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs index 534eb2dd..e5d719e4 100644 --- a/src/Mapster.Tests/WhenMappingRecordRegression.cs +++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs @@ -345,7 +345,7 @@ public void MappingInterfaceToInterface() ()=> updExt.ActivityData.ShouldBe(targetExtention.ActivityData), () => ((SampleActivityDataExtentions)updExt.ActivityData).Temp.ShouldBe(sourceDerived.ActivityData.Temp), () => ((SampleActivityDataExtentions)updExt.ActivityData).TempLength.ShouldBe(sourceDerived.ActivityData.Temp.Length), - // All implementations of the IActivityData interface do not provide access to the Data property for all implementations of the SampleActivityData class, + // IActivityData interface and all its derivatives do not provide access to the Data property for all implementations of the SampleActivityData class, // so this property will not be changed by mapping () => ((SampleActivityDataExtentions)updExt.ActivityData).Data.ShouldBe(((SampleActivityDataExtentions)targetExtention.ActivityData).Data)