I am trying to map a number of entities that come from EF Core backed by CosmosDB to an equivalent set of concrete types that implement an interface. For simplicity, In the example below I have just stripped it down to a List<T>
.
When I run my code I get an exception about IAccount
not having a default constructor.
`IAccount' does not have a default constructor (Parameter 'type')'
The error happens at var query = mapper.ProjectTo<IAccount>(repo);
. I have tried every combination of configuration that I can think of but I am stuck.
My current version is as follows, which is stripped down from my original classes. This is why AccountBase
exists, which isn't obvious from the example.
Source Types
public abstract class AccountEntity
{
public Guid Id { get; set; }
public abstract string Name { get; set; }
}
public class UserEntity : AccountEntity
{
public string Username { get; set; } = null!;
public string Email { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
public override string Name { get; set; } = null!;
}
public class OrganizationEntity : AccountEntity
{
public override string Name { get; set; } = null!;
public IEnumerable<string> Industries { get; set; } = null!;
public string? Website { get; set; }
}
Destination Types
public interface IAccount
{
Guid Id { get; }
string Name { get; }
}
public abstract class AccountBase : IAccount
{
public Guid Id { get; set; }
public string Name { get; set; } = null!;
}
public class User : AccountBase
{
public string Username { get; set; } = null!;
public string Email { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
}
public class Organization : AccountBase
{
public IEnumerable<string> Industries { get; } = null!;
public string? Website { get; set; }
}
Test
var config = new MapperConfiguration(c =>
{
c.CreateMap<AccountEntity, IAccount>()
.IncludeAllDerived();
c.CreateMap<UserEntity, IAccount>()
.As<User>();
c.CreateMap<UserEntity, User>();
c.CreateMap<OrganizationEntity, IAccount>()
.As<Organization>();
c.CreateMap<OrganizationEntity, Organization>();
});
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var repo = new List<AccountEntity>()
{
new UserEntity()
{
Id = Guid.NewGuid(),
FirstName = "First",
LastName = "User"
},
new OrganizationEntity()
{
Id = Guid.NewGuid(),
Industries = new [] { "SPACETRAVEL" },
Name = "Org 1"
}
}.AsQueryable();
var queryProjection = mapper.ProjectTo<IAccount>(repo);
var results = queryProjection.ToList();
My goal is to get an Organization
when OrganizationEntity
is encountered and likewise an User
for an UserEntity
.
I have tried .DisableCtorValidation()
and .ConvertUsing()
but those don't help in my testing.