Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/AutoMapper/QueryableExtensions/ProjectionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ private QueryExpressions CreateProjection(ProjectionRequest request)
private (TypeMap, TypeMap[]) GetPolymorphicMaps(in ProjectionRequest request)
{
var typeMap = _configuration.ResolveTypeMap(request.SourceType, request.DestinationType) ?? throw TypeMap.MissingMapException(request.SourceType, request.DestinationType);
return (typeMap, _configuration.GetIncludedTypeMaps(typeMap.IncludedDerivedTypes.Where(tp => tp.SourceType != typeMap.SourceType).DistinctBy(tp => tp.SourceType).ToArray()));
return (typeMap, _configuration.GetIncludedTypeMaps(typeMap.IncludedDerivedTypes
.Where(tp => tp.SourceType != typeMap.SourceType && !tp.DestinationType.IsAbstract).DistinctBy(tp => tp.SourceType).ToArray()));
}
public QueryExpressions CreateProjection(in ProjectionRequest request, LetPropertyMaps letPropertyMaps)
{
Expand All @@ -64,7 +65,9 @@ public QueryExpressions CreateProjection(in ProjectionRequest request, LetProper
QueryExpressions CreateProjection(in ProjectionRequest request, LetPropertyMaps letPropertyMaps, TypeMap typeMap, TypeMap[] polymorphicMaps)
{
var instanceParameter = Parameter(request.SourceType, "dto" + request.SourceType.Name);
var projection = CreateProjectionCore(request, instanceParameter, typeMap, letPropertyMaps);
var destinationType = typeMap.DestinationType;
var projection = polymorphicMaps.Length > 0 && destinationType.IsAbstract ?
Default(destinationType) : CreateProjectionCore(request, instanceParameter, typeMap, letPropertyMaps);
foreach(var derivedMap in polymorphicMaps)
{
var sourceType = derivedMap.SourceType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
namespace AutoMapper.IntegrationTests.Inheritance;

public class ProjectToAbstractTypeWithInheritance : IntegrationTest<ProjectToAbstractTypeWithInheritance.DatabaseInitializer>
{
public class StepGroup
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Step> Steps { get; set; } = new();
}
public abstract class Step
{
public int Id { get; set; }
public string Name { get; set; }
public int StepGroupId { get; set; }
public virtual StepGroup StepGroup { get; set; }
}
public class CheckingStep : Step { }
public class InstructionStep : Step { }
public abstract class AbstractStep : Step { }

public class StepGroupModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<StepModel> Steps { get; set; } = new();
}
public abstract class StepModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CheckingStepModel : StepModel { }
public class InstructionStepModel : StepModel { }
public abstract class AbstractStepModel : StepModel { }

public class Context : LocalDbContext
{
public DbSet<StepGroup> StepGroups { get; set; }

public DbSet<Step> Steps { get; set; }

public DbSet<CheckingStep> CheckingSteps { get; set; }

public DbSet<InstructionStep> InstructionSteps { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Step>(entity =>
{
entity.HasOne(d => d.StepGroup).WithMany(p => p.Steps)
.HasForeignKey(d => d.StepGroupId);
});
}
}

protected override MapperConfiguration CreateConfiguration()
{
return new MapperConfiguration(cfg =>
{
cfg.CreateMap<StepGroup, StepGroupModel>();
cfg.CreateMap<Step, StepModel>();
cfg.CreateMap<CheckingStep, CheckingStepModel>()
.IncludeBase<Step, StepModel>();
cfg.CreateMap<InstructionStep, InstructionStepModel>()
.IncludeBase<Step, StepModel>();
cfg.CreateMap<AbstractStep, AbstractStepModel>()
.IncludeBase<Step, StepModel>();
});
}

public class DatabaseInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
context.StepGroups.Add(new StepGroup
{
Name = "StepGroup",
Steps = new List<Step>
{
new InstructionStep
{
Name = "InstructionStep"
},
new CheckingStep
{
Name = "CheckingStep"
}
}
});

base.Seed(context);
}
}

[Fact]
public void ProjectCollectionWithElementInheritingAbstractClass()
{
using var context = new Context();
var steps = ProjectTo<StepGroupModel>(context.StepGroups).Single().Steps;
steps[0].ShouldBeOfType<CheckingStepModel>().Name.ShouldBe("CheckingStep");
steps[1].ShouldBeOfType<InstructionStepModel>().Name.ShouldBe("InstructionStep");
}
}