diff --git a/src/Mapster.Tests/WhenMappingObjectRegression.cs b/src/Mapster.Tests/WhenMappingObjectRegression.cs
new file mode 100644
index 00000000..d6cf7776
--- /dev/null
+++ b/src/Mapster.Tests/WhenMappingObjectRegression.cs
@@ -0,0 +1,156 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Shouldly;
+using System;
+
+namespace Mapster.Tests
+{
+ [TestClass]
+ public class WhenMappingObjectRegression
+ {
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/524
+ ///
+ [TestMethod]
+ public void TSourceIsObjectUpdate()
+ {
+ var source = new Source524 { X1 = 123 };
+ var _result = Somemap(source);
+
+ _result.X1.ShouldBe(123);
+ }
+
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/524
+ ///
+ [TestMethod]
+ public void TSourceIsObjectUpdateUseDynamicCast()
+ {
+ var source = new Source524 { X1 = 123 };
+ var _result = SomemapWithDynamic(source);
+
+ _result.X1.ShouldBe(123);
+ }
+
+ [TestMethod]
+ public void UpdateManyDest()
+ {
+ var source = new Source524 { X1 = 123 };
+ var _result = SomemapManyDest(source);
+
+ _result.X1.ShouldBe(123);
+ _result.X2.ShouldBe(127);
+ }
+
+ [TestMethod]
+ public void UpdateToRealObject()
+ {
+ var source = new Source524 { X1 = 123 };
+ var RealObject = new Object();
+
+ var _result = source.Adapt(RealObject);
+
+ _result.ShouldBeOfType();
+ ((Source524)_result).X1.ShouldBe(source.X1);
+
+ }
+
+ [TestMethod]
+ public void RealObjectCastToDestination() /// Warning potential Infinity Loop in ObjectAdapter!!!
+ {
+ var source = new Source524 { X1 = 123 };
+ var RealObject = new Object();
+
+ var _result = RealObject.Adapt(source);
+
+ _result.ShouldBeOfType();
+ ((Source524)_result).X1.ShouldBe(source.X1);
+ }
+
+ [TestMethod]
+ public void UpdateObjectInsaider()
+ {
+ var _source = new InsaderObject() { X1 = 1 };
+ var _Destination = new InsaderObject() { X1 = 2 };
+
+ var _result = _source.Adapt(_Destination);
+
+ _result.X1.ShouldBe(_source.X1);
+ }
+
+ [TestMethod]
+ public void UpdateObjectInsaiderToObject()
+ {
+ var _source = new InsaderObject() { X1 = 1 };
+ var _Destination = new InsaderObject() { X1 = new Object() };
+
+ var _result = _source.Adapt(_Destination);
+
+ _result.X1.ShouldBe(_source.X1);
+ }
+
+ [TestMethod]
+ public void UpdateObjectInsaiderWhenObjectinTSource()
+ {
+ var _source = new InsaderObject() { X1 = new Object() };
+ var _Destination = new InsaderObject() { X1 = 3 };
+
+ var _result = _source.Adapt(_Destination);
+
+ _result.X1.ShouldBe(_source.X1);
+ }
+
+
+ #region TestFunctions
+
+ Dest524 Somemap(object source)
+ {
+ var dest = new Dest524 { X1 = 321 };
+ var dest1 = source.Adapt(dest);
+
+ return dest;
+ }
+
+ ManyDest524 SomemapManyDest(object source)
+ {
+ var dest = new ManyDest524 { X1 = 321, X2 = 127 };
+ var dest1 = source.Adapt(dest);
+
+ return dest;
+ }
+
+ Dest524 SomemapWithDynamic(object source)
+ {
+ var dest = new Dest524 { X1 = 321 };
+ var dest1 = source.Adapt(dest, source.GetType(), dest.GetType());
+
+ return dest;
+ }
+
+ #endregion TestFunctions
+
+ #region TestClasses
+ class Source524
+ {
+ public int X1 { get; set; }
+ }
+ class Dest524
+ {
+ public int X1 { get; set; }
+ }
+
+ class ManyDest524
+ {
+ public int X1 { get; set;}
+
+ public int X2 { get; set;}
+ }
+
+ class InsaderObject
+ {
+ public Object X1 { get; set;}
+ }
+
+
+ #endregion TestClasses
+ }
+}
diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs
index f5ef6add..37bde9c4 100644
--- a/src/Mapster.Tests/WhenMappingRecordRegression.cs
+++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs
@@ -41,7 +41,7 @@ public void AdaptRecordStructToRecordStruct()
var _structResult = _sourceStruct.Adapt(_destinationStruct);
_structResult.X.ShouldBe(1000);
- object.ReferenceEquals(_destinationStruct, _structResult).ShouldBeFalse();
+ _structResult.X.ShouldNotBe(_destinationStruct.X);
}
[TestMethod]
@@ -194,26 +194,6 @@ public void UpdateNullable()
}
- ///
- /// https://github.com/MapsterMapper/Mapster/issues/524
- ///
- [TestMethod]
- public void TSousreIsObjectUpdateUseDynamicCast()
- {
- var source = new TestClassPublicCtr { X = 123 };
- var _result = SomemapWithDynamic(source);
-
- _result.X.ShouldBe(123);
- }
-
- TestClassPublicCtr SomemapWithDynamic(object source)
- {
- var dest = new TestClassPublicCtr { X = 321 };
- var dest1 = source.Adapt(dest,source.GetType(),dest.GetType());
-
- return dest;
- }
-
///
/// https://github.com/MapsterMapper/Mapster/issues/569
///
@@ -268,29 +248,6 @@ public void CollectionUpdate()
destination.Count.ShouldBe(_result.Count);
}
- ///
- /// https://github.com/MapsterMapper/Mapster/issues/524
- /// Not work. Already has a special overload:
- /// .Adapt(this object source, object destination, Type sourceType, Type destinationType)
- ///
- [Ignore]
- [TestMethod]
- public void TSousreIsObjectUpdate()
- {
- var source = new TestClassPublicCtr { X = 123 };
- var _result = Somemap(source);
-
- _result.X.ShouldBe(123);
- }
-
- TestClassPublicCtr Somemap(object source)
- {
- var dest = new TestClassPublicCtr { X = 321 };
- var dest1 = source.Adapt(dest); // typeof(TSource) always return Type as Object. Need use dynamic or Cast to Runtime Type before Adapt
-
- return dest;
- }
-
#endregion NowNotWorking
}
diff --git a/src/Mapster/TypeAdapter.cs b/src/Mapster/TypeAdapter.cs
index 2e1db2f1..0b92359b 100644
--- a/src/Mapster/TypeAdapter.cs
+++ b/src/Mapster/TypeAdapter.cs
@@ -93,10 +93,37 @@ public static TDestination Adapt(this TSource source, TDe
/// 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.
///