diff --git a/src/Mapster.Tests/WhenIncludeDerivedClasses.cs b/src/Mapster.Tests/WhenIncludeDerivedClasses.cs
index 3002766a..3af19256 100644
--- a/src/Mapster.Tests/WhenIncludeDerivedClasses.cs
+++ b/src/Mapster.Tests/WhenIncludeDerivedClasses.cs
@@ -40,6 +40,37 @@ public void Map_Including_Derived_Class_With_List()
((BikeDto)dto[1]).Brand.ShouldBe("BMX");
}
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/801
+ ///
+ [TestMethod]
+ public void CompileProjection_Including_Derived_Class()
+ {
+ TypeAdapterConfig.NewConfig()
+ .Include()
+ .CompileProjection();
+ }
+
+ public abstract class PocoA801
+ {
+ public int Id { get; set; }
+ }
+
+ public class PocoDerived801 : PocoA801
+ {
+ public int DerivedVal { get; set; }
+ }
+
+ public abstract class DtoA801
+ {
+ public int Id { get; set; }
+ }
+
+ public class DtoDerived801 : DtoA801
+ {
+ public int DerivedVal { get; set; }
+ }
+
#region test classes
public abstract class Vehicle
{
diff --git a/src/Mapster.Tests/WhenMappingRecordRegression.cs b/src/Mapster.Tests/WhenMappingRecordRegression.cs
index 13ff3ea3..bcf0c96e 100644
--- a/src/Mapster.Tests/WhenMappingRecordRegression.cs
+++ b/src/Mapster.Tests/WhenMappingRecordRegression.cs
@@ -539,6 +539,49 @@ public void NotSelfCreationTypeMappingToSelfWithOutError()
resultJ.RootElement.GetProperty("key").ToString().ShouldBe("value");
}
+ ///
+ /// https://github.com/MapsterMapper/Mapster/issues/911
+ ///
+ [TestMethod]
+ public void NotSelfCreationTypeMappingInContainingClassWithoutError()
+ {
+ var jsonSource = new SourceClassWithJsonDocument911
+ {
+ Json = JsonDocument.Parse("{\"key\": \"value\"}")
+ };
+
+ var uriSource = new SourceClassWithUri911
+ {
+ Uri = new Uri("https://www.google.com/")
+ };
+
+ var jsonDest = jsonSource.Adapt();
+ var uriDest = uriSource.Adapt();
+
+ jsonDest.Json.RootElement.GetProperty("key").GetString().ShouldBe("value");
+ uriDest.Uri.ToString().ShouldBe("https://www.google.com/");
+ }
+
+ class SourceClassWithJsonDocument911
+ {
+ public required JsonDocument Json { get; init; }
+ }
+
+ class DestinationClassWithJsonDocument911
+ {
+ public required JsonDocument Json { get; init; }
+ }
+
+ class SourceClassWithUri911
+ {
+ public required Uri Uri { get; init; }
+ }
+
+ class DestinationClassWithUri911
+ {
+ public required Uri Uri { get; init; }
+ }
+
///
/// https://github.com/MapsterMapper/Mapster/issues/927
///
diff --git a/src/Mapster/Adapters/ClassAdapter.cs b/src/Mapster/Adapters/ClassAdapter.cs
index 27d09d9b..d71067b0 100644
--- a/src/Mapster/Adapters/ClassAdapter.cs
+++ b/src/Mapster/Adapters/ClassAdapter.cs
@@ -219,9 +219,17 @@ private static Expression SetValueByReflection(MemberMapping member, MemberExpre
// Prop2 = convert(src.Prop2),
//}
+ if (arg.MapType == MapType.Projection && arg.DestinationType.IsAbstract && arg.Settings.Includes.Count > 0)
+ return CreateIncludeProjectionExpression(source, arg);
+
var exp = CreateInstantiationExpression(source, arg);
+ if (exp.NodeType == ExpressionType.Throw)
+ return null;
+
var memberInit = exp as MemberInitExpression;
- var newInstance = memberInit?.NewExpression ?? (NewExpression)exp;
+ var newInstance = memberInit?.NewExpression ?? exp as NewExpression;
+ if (newInstance == null)
+ return null;
var contructorMembers = newInstance.GetAllMemberExpressionsMemberInfo().ToArray();
ClassModel? classModel;
ClassMapping? classConverter;
@@ -272,6 +280,36 @@ private static Expression SetValueByReflection(MemberMapping member, MemberExpre
return Expression.MemberInit(newInstance, lines);
}
+ static Expression CreateIncludeProjectionExpression(Expression source, CompileArgument arg)
+ {
+ Expression body = Expression.Default(arg.DestinationType);
+ foreach (var tuple in arg.Settings.Includes)
+ {
+ var itemTuple = tuple;
+ if (tuple.Source.IsOpenGenericType() && tuple.Destination.IsOpenGenericType())
+ {
+ var genericArg = source.Type.GetGenericArguments();
+ itemTuple = new TypeTuple(tuple.Source.MakeGenericType(genericArg), tuple.Destination.MakeGenericType(genericArg));
+ }
+
+ if (itemTuple.Source == arg.SourceType)
+ continue;
+
+ if (!arg.SourceType.GetTypeInfo().IsAssignableFrom(itemTuple.Source.GetTypeInfo()))
+ continue;
+
+ if (!arg.DestinationType.GetTypeInfo().IsAssignableFrom(itemTuple.Destination.GetTypeInfo()))
+ continue;
+
+ var test = Expression.TypeIs(source, itemTuple.Source);
+ var cast = Expression.TypeAs(source, itemTuple.Source);
+ var mapped = CreateAdaptExpressionCore(cast!, itemTuple.Destination, arg);
+ body = Expression.Condition(test, mapped.To(arg.DestinationType, true), body);
+ }
+
+ return body;
+ }
+
protected override Expression CreateExpressionBody(Expression source, Expression? destination, CompileArgument arg)
{
TypeAdapterRule? rule;