diff --git a/src/Mapster.Tests/WhenForkingConfig.cs b/src/Mapster.Tests/WhenForkingConfig.cs index 84b37d37..59aa9050 100644 --- a/src/Mapster.Tests/WhenForkingConfig.cs +++ b/src/Mapster.Tests/WhenForkingConfig.cs @@ -65,7 +65,7 @@ public void Fork_Setting() dto.Name1.ShouldBe(poco.Name1); dto.Name2.ShouldBe("Bar"); - var str = poco.Name2.Adapt(dto.Name2, config); + var str = poco.Name2.AdaptToTarget(dto.Name2, config); str.ShouldBe(poco.Name2); } diff --git a/src/Mapster.Tests/WhenIgnoreMapping.cs b/src/Mapster.Tests/WhenIgnoreMapping.cs index 245c4e63..b5d3eef3 100644 --- a/src/Mapster.Tests/WhenIgnoreMapping.cs +++ b/src/Mapster.Tests/WhenIgnoreMapping.cs @@ -83,7 +83,7 @@ public void WhenClassIgnoreCtorParamGetDefaultValue() var dest = new B707(123, "Hello"); var docKind = source.Adapt(config); - var mapTotarget = source.Adapt(dest,config); + var mapTotarget = source.AdaptToTarget(dest,config); docKind.Id.ShouldBe(0); mapTotarget.Id.ShouldBe(123); diff --git a/src/Mapster.Tests/WhenMappingIgnoreNullValues.cs b/src/Mapster.Tests/WhenMappingIgnoreNullValues.cs index e98dffb7..d420849e 100644 --- a/src/Mapster.Tests/WhenMappingIgnoreNullValues.cs +++ b/src/Mapster.Tests/WhenMappingIgnoreNullValues.cs @@ -31,7 +31,7 @@ public void Map_To_Target() .Compile(); var source = new SourceClass(); - var dest = source.Adapt(new DestClass()); + var dest = source.AdaptToTarget(new DestClass()); Assert.AreEqual("Hello", dest.Title); Assert.IsNotNull(dest.Sub); diff --git a/src/Mapster.Tests/WhenMappingInitProperty.cs b/src/Mapster.Tests/WhenMappingInitProperty.cs index 6c1352de..7dc55d18 100644 --- a/src/Mapster.Tests/WhenMappingInitProperty.cs +++ b/src/Mapster.Tests/WhenMappingInitProperty.cs @@ -17,7 +17,7 @@ public void WhenMappingToHiddenandNewInitFieldDestination() { var source = new Source672() { Id = 156}; var c = source.Adapt(); - var s = source.Adapt(new BDestination()); + var s = source.AdaptToTarget(new BDestination()); ((ADestination)c).Id.ShouldBe(default); // Hidden Base member is not mapping s.Id.ShouldBe(156); @@ -31,7 +31,7 @@ public void WhenMappingToHiddenandNewInitFieldWithConstructUsing() var source = new Source672() { Id = 256 }; var c = source.Adapt(); - var s = source.Adapt(new BDestination()); + var s = source.AdaptToTarget(new BDestination()); ((ADestination)c).Id.ShouldBe(default); // Hidden Base member is not mapping s.Id.ShouldBe(256); diff --git a/src/Mapster.Tests/WhenMappingNullableEnumRegression.cs b/src/Mapster.Tests/WhenMappingNullableEnumRegression.cs index c6b4281e..9276002a 100644 --- a/src/Mapster.Tests/WhenMappingNullableEnumRegression.cs +++ b/src/Mapster.Tests/WhenMappingNullableEnumRegression.cs @@ -47,7 +47,7 @@ public void UpdateNullEnumToClass() var mDest2 = new MyDestination() { TypeEmployer = new KeyValueData("Admin", null) }; var _MyDestination = myClass?.Adapt(); // Work - var _result = _MyDestination.Adapt(mDest2); + var _result = _MyDestination.AdaptToTarget(mDest2); _result.TypeEmployer.Key.ShouldBe(MyEnum.User.ToString()); } diff --git a/src/Mapster.Tests/WhenMappingObjectRegression.cs b/src/Mapster.Tests/WhenMappingObjectRegression.cs index d6cf7776..45bb1972 100644 --- a/src/Mapster.Tests/WhenMappingObjectRegression.cs +++ b/src/Mapster.Tests/WhenMappingObjectRegression.cs @@ -47,7 +47,7 @@ public void UpdateToRealObject() var source = new Source524 { X1 = 123 }; var RealObject = new Object(); - var _result = source.Adapt(RealObject); + var _result = source.AdaptToTarget(RealObject); _result.ShouldBeOfType(); ((Source524)_result).X1.ShouldBe(source.X1); @@ -60,7 +60,7 @@ public void RealObjectCastToDestination() /// Warning potential Infinity Loop in var source = new Source524 { X1 = 123 }; var RealObject = new Object(); - var _result = RealObject.Adapt(source); + var _result = RealObject.AdaptToTarget(source); _result.ShouldBeOfType(); ((Source524)_result).X1.ShouldBe(source.X1); @@ -72,7 +72,7 @@ public void UpdateObjectInsaider() var _source = new InsaderObject() { X1 = 1 }; var _Destination = new InsaderObject() { X1 = 2 }; - var _result = _source.Adapt(_Destination); + var _result = _source.AdaptToTarget(_Destination); _result.X1.ShouldBe(_source.X1); } @@ -83,7 +83,7 @@ public void UpdateObjectInsaiderToObject() var _source = new InsaderObject() { X1 = 1 }; var _Destination = new InsaderObject() { X1 = new Object() }; - var _result = _source.Adapt(_Destination); + var _result = _source.AdaptToTarget(_Destination); _result.X1.ShouldBe(_source.X1); } @@ -94,7 +94,7 @@ public void UpdateObjectInsaiderWhenObjectinTSource() var _source = new InsaderObject() { X1 = new Object() }; var _Destination = new InsaderObject() { X1 = 3 }; - var _result = _source.Adapt(_Destination); + var _result = _source.AdaptToTarget(_Destination); _result.X1.ShouldBe(_source.X1); } @@ -105,7 +105,7 @@ public void UpdateObjectInsaiderWhenObjectinTSource() Dest524 Somemap(object source) { var dest = new Dest524 { X1 = 321 }; - var dest1 = source.Adapt(dest); + var dest1 = source.AdaptToTarget(dest); return dest; } @@ -113,7 +113,7 @@ Dest524 Somemap(object source) ManyDest524 SomemapManyDest(object source) { var dest = new ManyDest524 { X1 = 321, X2 = 127 }; - var dest1 = source.Adapt(dest); + var dest1 = source.AdaptToTarget(dest); return dest; } diff --git a/src/Mapster.Tests/WhenMappingPrimitiveCustomMappingRegression.cs b/src/Mapster.Tests/WhenMappingPrimitiveCustomMappingRegression.cs index d694ac67..76b1b8c8 100644 --- a/src/Mapster.Tests/WhenMappingPrimitiveCustomMappingRegression.cs +++ b/src/Mapster.Tests/WhenMappingPrimitiveCustomMappingRegression.cs @@ -44,8 +44,8 @@ public void MappingToPrimitiveInsiderWithCustomMapping() var target = new Source561 { Name = new Optional561("John") }.Adapt(); var TargetDestinationFromNull = new Target561() { Name = "Me" }; - var NullToupdateoptional = sourceNull.Adapt(TargetDestinationFromNull); - var _result = sourceNull.Adapt(target); + var NullToupdateoptional = sourceNull.AdaptToTarget(TargetDestinationFromNull); + var _result = sourceNull.AdaptToTarget(target); target.Name.ShouldBe("John"); NullToupdateoptional.Name.ShouldBe("Me"); diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs index 9ba98adb..305dae77 100644 --- a/src/Mapster.Tests/WhenMappingRecordRegression.cs +++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs @@ -21,11 +21,10 @@ public void AdaptRecordToRecord() var _source = new TestRecord() { X = 700 }; var _destination = new TestRecordY() { X = 500 , Y = 200 }; - var _destination2 = new TestRecordY() { X = 300, Y = 400 }; - var _result = _source.Adapt(_destination); - - var result2 = _destination.Adapt(_destination2); + + var _result = _source.AdaptToTarget(_destination); + var result2 = _destination.AdaptToTarget(_destination2); _result.X.ShouldBe(700); _result.Y.ShouldBe(200); @@ -37,7 +36,7 @@ public void AdaptPositionalRecordToPositionalRecord() { var _sourcePositional = new TestRecordPositional(600); var _destinationPositional = new TestRecordPositional(900); - var _positionalResult = _sourcePositional.Adapt(_destinationPositional); + var _positionalResult = _sourcePositional.AdaptToTarget(_destinationPositional); _positionalResult.X.ShouldBe(600); object.ReferenceEquals(_destinationPositional, _positionalResult).ShouldBeFalse(); @@ -48,7 +47,7 @@ public void AdaptRecordStructToRecordStruct() { var _sourceStruct = new TestRecordStruct() { X = 1000 }; var _destinationStruct = new TestRecordStruct() { X = 800 }; - var _structResult = _sourceStruct.Adapt(_destinationStruct); + var _structResult = _sourceStruct.AdaptToTarget(_destinationStruct); _structResult.X.ShouldBe(1000); _destinationStruct.X.Equals(_structResult.X).ShouldBeFalse(); @@ -59,7 +58,7 @@ public void AdaptRecordToClass() { var _sourсe = new TestRecordPositional(200); var _destination = new TestClassProtectedCtr(400); - var _result = _sourсe.Adapt(_destination); + var _result = _sourсe.AdaptToTarget(_destination); _destination.ShouldBeOfType(); _destination.X.ShouldBe(200); @@ -71,7 +70,7 @@ public void AdaptClassToRecord() { var _sourсe = new TestClassProtectedCtr(200); var _destination = new TestRecordPositional(400); - var _result = _sourсe.Adapt(_destination); + var _result = _sourсe.AdaptToTarget(_destination); _destination.ShouldBeOfType(); _result.X.ShouldBe(200); @@ -83,7 +82,7 @@ public void AdaptToSealtedRecord() { var _sourceRecord = new TestRecord() { X = 2000 }; var _destinationSealtedRecord = new TestSealedRecord() { X = 3000 }; - var _RecordResult = _sourceRecord.Adapt(_destinationSealtedRecord); + var _RecordResult = _sourceRecord.AdaptToTarget(_destinationSealtedRecord); _RecordResult.X.ShouldBe(2000); object.ReferenceEquals(_destinationSealtedRecord, _RecordResult).ShouldBeFalse(); @@ -94,7 +93,7 @@ public void AdaptToSealtedPositionalRecord() { var _sourceRecord = new TestRecord() { X = 2000 }; var _destinationSealtedPositionalRecord = new TestSealedRecordPositional(4000); - var _RecordResult = _sourceRecord.Adapt(_destinationSealtedPositionalRecord); + var _RecordResult = _sourceRecord.AdaptToTarget(_destinationSealtedPositionalRecord); _RecordResult.X.ShouldBe(2000); object.ReferenceEquals(_destinationSealtedPositionalRecord, _RecordResult).ShouldBeFalse(); @@ -105,7 +104,7 @@ public void AdaptClassToClassPublicCtrIsNotInstanse() { var _source = new TestClassPublicCtr(200); var _destination = new TestClassPublicCtr(400); - var _result = _source.Adapt(_destination); + var _result = _source.AdaptToTarget(_destination); _destination.ShouldBeOfType(); _destination.X.ShouldBe(200); @@ -117,7 +116,7 @@ public void AdaptClassToClassProtectdCtrIsNotInstanse() { var _source = new TestClassPublicCtr(200); var _destination = new TestClassProtectedCtr(400); - var _result = _source.Adapt(_destination); + var _result = _source.AdaptToTarget(_destination); _destination.ShouldBeOfType(); _destination.X.ShouldBe(200); @@ -154,7 +153,7 @@ public void AdaptClassToClassFromPrivatePropertyIsNotInstanse() { var _source = new TestClassPublicCtr(200); var _destination = new TestClassProtectedCtrPrivateProperty(400, "Me"); - var _result = _source.Adapt(_destination); + var _result = _source.AdaptToTarget(_destination); _destination.ShouldBeOfType(); _destination.X.ShouldBe(200); @@ -191,7 +190,7 @@ public void UpdateNullable() config.ForType() .IgnoreNullValues(true); - var _resultEmail = _updateEmail.Adapt(_sourceEmailUpdate, config); + var _resultEmail = _updateEmail.AdaptToTarget(_sourceEmailUpdate, config); _source.Id.ShouldBe("123"); _source.Created.ShouldBe(new DateTime(2023, 9, 24)); @@ -220,7 +219,7 @@ public void ImplicitOperatorCurrentWorkFromClass() pocoWithId1.Id.ToString().Equals(guid.ToString()).ShouldBeTrue(); pocoWithGuid2.Id.Equals(guid).ShouldBeTrue(); - var _result = pocoWithId1.Adapt(pocoWithGuid2); + var _result = pocoWithId1.AdaptToTarget(pocoWithGuid2); _result.Id.ToString().Equals(guid.ToString()).ShouldBeTrue(); // Guid value transmitted object.ReferenceEquals(_result, pocoWithGuid2).ShouldBeTrue(); // Not created new instanse from class pocoWithGuid2 @@ -233,7 +232,7 @@ public void DetectFakeRecord() { var _source = new TestClassPublicCtr(200); var _destination = new FakeRecord { X = 300 }; - var _result = _source.Adapt(_destination); + var _result = _source.AdaptToTarget(_destination); _destination.X.ShouldBe(200); object.ReferenceEquals(_destination, _result).ShouldBeTrue(); } @@ -245,7 +244,7 @@ public void OnlyInlineRecordWorked() var _sourceOnlyInitRecord = new OnlyInitRecord501 { MyInt = 2, MyString = "Hello World" }; var _resultOnlyinitRecord = _sourcePoco.Adapt(); - var _updateResult = _sourceOnlyInitRecord.Adapt(_resultOnlyinitRecord); + var _updateResult = _sourceOnlyInitRecord.AdaptToTarget(_resultOnlyinitRecord); _resultOnlyinitRecord.MyInt.ShouldBe(1); _resultOnlyinitRecord.MyString.ShouldBe("Hello"); @@ -260,7 +259,7 @@ public void MultyCtorRecordWorked() var _sourceMultyCtorRecord = new MultiCtorRecord (2, "Hello World"); var _resultMultyCtorRecord = _sourcePoco.Adapt(); - var _updateResult = _sourceMultyCtorRecord.Adapt(_resultMultyCtorRecord); + var _updateResult = _sourceMultyCtorRecord.AdaptToTarget(_resultMultyCtorRecord); _resultMultyCtorRecord.MyInt.ShouldBe(1); _resultMultyCtorRecord.MyString.ShouldBe("Hello"); @@ -275,7 +274,7 @@ public void MultiCtorAndInlineRecordWorked() var _sourceMultiCtorAndInline = new MultiCtorAndInlineRecord(2, "Hello World") { InitData = "Worked", MyEmail = "243@gmail.com" }; var _resultMultiCtorAndInline = _sourcePoco.Adapt(); - var _updateResult = _sourceMultiCtorAndInline.Adapt(_resultMultiCtorAndInline); + var _updateResult = _sourceMultiCtorAndInline.AdaptToTarget(_resultMultiCtorAndInline); _resultMultiCtorAndInline.MyInt.ShouldBe(1); _resultMultiCtorAndInline.MyString.ShouldBe("Hello"); @@ -340,12 +339,12 @@ public void MappingInterfaceToInterface() var TargetBase = sourceBase.Adapt(); var targetDerived = sourceDerived.Adapt(); - var update = targetDerived.Adapt(TargetBase); + var update = targetDerived.AdaptToTarget(TargetBase); var targetExtention = sourceExt.Adapt(); - var updExt = targetDerived.Adapt(targetExtention); + var updExt = targetDerived.AdaptToTarget(targetExtention); targetDerived.ShouldNotBeNull(); targetDerived.ShouldSatisfyAllConditions( @@ -381,9 +380,9 @@ public void WhenRecordReceivedIgnoreCtorParamProcessing() var UserInsider = new UserInside(user, new UserRecord456("Skot")); var map = userDto.Adapt(); - var maptoTarget = userDto.Adapt(user); + var maptoTarget = userDto.AdaptToTarget(user); - var MapToTargetInsider = DtoInsider.Adapt(UserInsider); + var MapToTargetInsider = DtoInsider.AdaptToTarget(UserInsider); map.Name.ShouldBeNullOrEmpty(); // Ignore is work set default value maptoTarget.Name.ShouldBe("John"); // Ignore is work ignored member save value from Destination @@ -409,7 +408,7 @@ public void WhenRecordTypeWorksWithUseDestinationValueAndIgnoreNullValues() var txt = _sourceFromMapToTarget.BuildAdapter().CreateMapToTargetExpression(); - var _resultMapToTarget = _sourceFromMapToTarget.Adapt(result); + var _resultMapToTarget = _sourceFromMapToTarget.AdaptToTarget(result); result.A.ShouldBe(0); // default Value - not match result.S.ShouldBe("Inside Data"); // is not AutoProperty not mod by source @@ -436,7 +435,7 @@ public void FixCtorParamMapping() var result = new CreateOrderRequest771(sourceRequestOrderDto).Adapt(); - var resultID = db.Adapt(new Database746()); + var resultID = db.AdaptToTarget(new Database746()); result.Order.Payment.CVV.ShouldBe("234"); @@ -455,7 +454,7 @@ public void RequiredProperty() var s = source.BuildAdapter().CreateMapToTargetExpression(); - var result = source.Adapt(destination); + var result = source.AdaptToTarget(destination); result.ID.ShouldBe(245); result.FirstMidName.ShouldBe(source.FirstMidName); @@ -477,7 +476,7 @@ public void CollectionUpdate() new(234) }; var destination = new List(); - var _result = sources.Adapt(destination); + var _result = sources.AdaptToTarget(destination); destination.Count.ShouldBe(_result.Count); } diff --git a/src/Mapster.Tests/WhenMappingStructRegression.cs b/src/Mapster.Tests/WhenMappingStructRegression.cs index 43ad1882..ad569421 100644 --- a/src/Mapster.Tests/WhenMappingStructRegression.cs +++ b/src/Mapster.Tests/WhenMappingStructRegression.cs @@ -49,7 +49,7 @@ public void TestMapStructToExistingStruct() { Ignore = "Ignored property", }; - dest = source.Adapt(dest); + dest = source.AdaptToTarget(dest); dest.Ignore.ShouldBe("Ignored property"); dest.Name.ShouldBe("Some Name"); @@ -71,7 +71,7 @@ public void TestMapClassToExistingStruct() { Ignore = "Ignored property", }; - dest = source.Adapt(dest); + dest = source.AdaptToTarget(dest); dest.Ignore.ShouldBe("Ignored property"); dest.Name.ShouldBe("Some Name"); diff --git a/src/Mapster.Tests/WhenMappingWithAdaptIgnoreRegression.cs b/src/Mapster.Tests/WhenMappingWithAdaptIgnoreRegression.cs index 13638083..4254bbde 100644 --- a/src/Mapster.Tests/WhenMappingWithAdaptIgnoreRegression.cs +++ b/src/Mapster.Tests/WhenMappingWithAdaptIgnoreRegression.cs @@ -47,7 +47,7 @@ public void TestMapStructToExistingStruct() var destination = new Poco() { Name = "Destination", State = 2 }; var source = new Dto() { Name = "Source" }; - var result = source.Adapt(destination); + var result = source.AdaptToTarget(destination); result.State.ShouldBe(2); result.Name.ShouldBe("Source"); } diff --git a/src/Mapster.Tests/WhenMappingWithSecondSourceObject.cs b/src/Mapster.Tests/WhenMappingWithSecondSourceObject.cs index a3b31181..13b9e530 100644 --- a/src/Mapster.Tests/WhenMappingWithSecondSourceObject.cs +++ b/src/Mapster.Tests/WhenMappingWithSecondSourceObject.cs @@ -53,7 +53,7 @@ public void TestMapFromSecondSourceObject() generatedType.Name.ShouldBe("Name 1"); generatedType.Address.ShouldBe("Address 1"); - generatedType = c2.Adapt(generatedType); + generatedType = c2.AdaptToTarget(generatedType); generatedType.Id.ShouldBe(2); generatedType.Name.ShouldBe("Name 2"); diff --git a/src/Mapster.Tests/WhenPerformingAfterMapping.cs b/src/Mapster.Tests/WhenPerformingAfterMapping.cs index 68b06a62..e2442702 100644 --- a/src/Mapster.Tests/WhenPerformingAfterMapping.cs +++ b/src/Mapster.Tests/WhenPerformingAfterMapping.cs @@ -87,7 +87,7 @@ public void MapToTarget_Support_Destination_Parameter() Name = "test", }; var oldDto = new SimpleDto { Name = "zzz", }; - var result = poco.Adapt(oldDto); + var result = poco.AdaptToTarget(oldDto); result.ShouldNotBeSameAs(oldDto); result.Id.ShouldBe(poco.Id); diff --git a/src/Mapster.Tests/WhenPerformingBeforeMapping.cs b/src/Mapster.Tests/WhenPerformingBeforeMapping.cs index 5c000802..1068f293 100644 --- a/src/Mapster.Tests/WhenPerformingBeforeMapping.cs +++ b/src/Mapster.Tests/WhenPerformingBeforeMapping.cs @@ -67,7 +67,7 @@ public void MapToTarget_Support_Destination_Parameter() IEnumerable source = new List { 1, 2, 3, }; IEnumerable destination = new List { 0, }; - var result = source.Adapt(destination); + var result = source.AdaptToTarget(destination); destination.ShouldBe(new List { 0, }); source.ShouldBe(new List { 1, 2, 3, }); diff --git a/src/Mapster/Mapster.csproj b/src/Mapster/Mapster.csproj index f8299fd2..b3f66b00 100644 --- a/src/Mapster/Mapster.csproj +++ b/src/Mapster/Mapster.csproj @@ -29,4 +29,7 @@ + + + \ No newline at end of file diff --git a/src/Mapster/TypeAdapter.cs b/src/Mapster/TypeAdapter.cs index 7a42ab4a..ec1b1a6e 100644 --- a/src/Mapster/TypeAdapter.cs +++ b/src/Mapster/TypeAdapter.cs @@ -7,7 +7,7 @@ namespace Mapster { - public static class TypeAdapter + public static partial class TypeAdapter { public static ITypeAdapterBuilder BuildAdapter(this TSource source) { @@ -75,61 +75,6 @@ public static TDestination Adapt(this TSource source, Typ return fn(source); } - /// - /// Adapt the source object to the existing destination object. - /// - /// Source type. - /// Destination type. - /// Source object to adapt. - /// The destination object to populate. - /// Adapted destination type. - public static TDestination Adapt(this TSource source, TDestination destination) - { - return Adapt(source, destination, TypeAdapterConfig.GlobalSettings); - } - - /// - /// Adapt the source object to the existing destination object. - /// - /// Source type. - /// Destination type. - /// Source object to adapt. - /// The destination object to populate. - /// Configuration - /// Adapted destination type. - public static TDestination Adapt(this TSource source, TDestination destination, TypeAdapterConfig config) - { - var sourceType = source?.GetType(); - var destinationType = destination?.GetType(); - - if (sourceType == typeof(object)) // Infinity loop in ObjectAdapter if Runtime Type of source is Object - return destination; - - if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object)) - return UpdateFuncFromPackedinObject(source, destination, config, sourceType, destinationType); - - var fn = config.GetMapToTargetFunction(); - return fn(source, destination); - } - - private static TDestination UpdateFuncFromPackedinObject(TSource source, TDestination destination, TypeAdapterConfig config, Type sourceType, Type destinationType) - { - dynamic del = config.GetMapToTargetFunction(sourceType, destinationType); - - - if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible) - { - dynamic objfn = del; - return objfn((dynamic)source, (dynamic)destination); - } - else - { - //NOTE: if type is non-public, we cannot use dynamic - //DynamicInvoke is slow, but works with non-public - return (TDestination)del.DynamicInvoke(source, destination); - } - } - /// /// Adapt the source object to the destination type. /// @@ -170,45 +115,7 @@ private static TDestination UpdateFuncFromPackedinObject( //DynamicInvoke is slow, but works with non-public return del.DynamicInvoke(source); } - } - - /// - /// Adapt the source object to an existing destination object. - /// - /// Source object to adapt. - /// Destination object to populate. - /// The type of the source object. - /// The type of the destination object. - /// Adapted destination type. - public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType) - { - return Adapt(source, destination, sourceType, destinationType, TypeAdapterConfig.GlobalSettings); - } - - /// - /// Adapt the source object to an existing destination object. - /// - /// Source object to adapt. - /// Destination object to populate. - /// The type of the source object. - /// The type of the destination object. - /// Configuration - /// Adapted destination type. - public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType, TypeAdapterConfig config) - { - var del = config.GetMapToTargetFunction(sourceType, destinationType); - if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible) - { - dynamic fn = del; - return fn((dynamic)source, (dynamic)destination); - } - else - { - //NOTE: if type is non-public, we cannot use dynamic - //DynamicInvoke is slow, but works with non-public - return del.DynamicInvoke(source, destination); - } - } + } /// /// Validate properties and Adapt the source object to the destination type. diff --git a/src/Mapster/TypeAdapters/TypeAdapterToTarget.cs b/src/Mapster/TypeAdapters/TypeAdapterToTarget.cs new file mode 100644 index 00000000..74b3013c --- /dev/null +++ b/src/Mapster/TypeAdapters/TypeAdapterToTarget.cs @@ -0,0 +1,120 @@ +using System; +using System.Reflection; + +namespace Mapster +{ + public static partial class TypeAdapter + { + /// + /// Adapt the source object to the existing destination object. + /// + /// Source type. + /// Destination type. + /// Source object to adapt. + /// The destination object to populate. + /// Configuration + public static void Adapt(this TSource source, TDestination destination, TypeAdapterConfig? config = null) where TDestination : class + { + if (typeof(TDestination).IsRecordType()) + throw new InvalidOperationException($"Type: {typeof(TDestination).Name} is Immutable Using AdaptToTarget"); + + var sourceType = source?.GetType(); + var destinationType = destination?.GetType(); + + if(config is null) + config = TypeAdapterConfig.GlobalSettings; + + if (sourceType == typeof(object)) // Infinity loop in ObjectAdapter if Runtime Type of source is Object + return; + + if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object)) + UpdateFuncFromPackedinObject(source, destination, config, sourceType, destinationType); + + var fn = config.GetMapToTargetFunction(); + fn(source, destination); + } + + /// + /// Adapt the source object to an existing destination object. + /// + /// Source object to adapt. + /// Destination object to populate. + /// The type of the source object. + /// The type of the destination object. + /// Adapted destination type. + public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType) + { + return Adapt(source, destination, sourceType, destinationType, TypeAdapterConfig.GlobalSettings); + } + + /// + /// Adapt the source object to an existing destination object. + /// + /// Source object to adapt. + /// Destination object to populate. + /// The type of the source object. + /// The type of the destination object. + /// Configuration + /// Adapted destination type. + public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType, TypeAdapterConfig config) + { + var del = config.GetMapToTargetFunction(sourceType, destinationType); + if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible) + { + dynamic fn = del; + return fn((dynamic)source, (dynamic)destination); + } + else + { + //NOTE: if type is non-public, we cannot use dynamic + //DynamicInvoke is slow, but works with non-public + return del.DynamicInvoke(source, destination); + } + } + + /// + /// Adapt the source object to the Immutable type base object. + /// + /// Source type. + /// Destination type. + /// Source object to adapt. + /// Instance of Immutable type. + /// Configuration + /// Nondestructive mutation baseValue using tranformed from source object values + public static TDestination AdaptToTarget(this TSource source, TDestination baseValue, TypeAdapterConfig? config = null) + { + var sourceType = source?.GetType(); + var destinationType = baseValue?.GetType(); + + if (config is null) + config = TypeAdapterConfig.GlobalSettings; + + if (sourceType == typeof(object)) // Infinity loop in ObjectAdapter if Runtime Type of source is Object + return baseValue; + + if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object)) + return UpdateFuncFromPackedinObject(source, baseValue, config, sourceType, destinationType); + + var fn = config.GetMapToTargetFunction(); + return fn(source, baseValue); + } + + private static TDestination UpdateFuncFromPackedinObject(TSource source, TDestination destination, TypeAdapterConfig config, Type sourceType, Type destinationType) + { + dynamic del = config.GetMapToTargetFunction(sourceType, destinationType); + + + if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible) + { + dynamic objfn = del; + return objfn((dynamic)source, (dynamic)destination); + } + else + { + //NOTE: if type is non-public, we cannot use dynamic + //DynamicInvoke is slow, but works with non-public + return (TDestination)del.DynamicInvoke(source, destination); + } + } + } +}