使用AutoMapper从接口映射到具体类型 [英] Use AutoMapper to map from an interface to a concrete type

查看:249
本文介绍了使用AutoMapper从接口映射到具体类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我要执行的操作的简化示例……假设我具有以下接口:

Here's a simplified example of what I'm trying to do... let's say I have an the following interfaces:

public interface IPerson
{   
    int Id { get; set; }     
}

public interface IModelPerson : IPerson
{
    int BeautyCompetitionsWon { get; set; }
}

在实际的实现中,有很多不同类型的人(例如IUglyPerson等).这些是实体类型的合同,例如如下:

In the real implementation, there are lots of different types of people (e.g. IUglyPerson, etc). These are the contracts for entity types, e.g. as follows:

public class PersonEntity : IPerson
{
    public int Id { get; set; }
}

public class ModelPersonEntity : PersonEntity, IModelPerson
{
    public int BeautyCompetitionsWon { get; set; }
}

注意:对于每种合同类型,我们可能还会有多种实现方式-例如IModelPerson也可以由SupermodelEntity实现.

Note: We may also have multiple implementations of each contract type - e.g. IModelPerson may also be implemented by SupermodelEntity.

我们想将实体类型映射到DTO,如下所示:

We want to map our entity types to DTOs, which look something like this:

public abstract class PersonDto : IPerson
{
    public int Id { get; set; }
    public abstract string PersonType { get; }
}

public class ModelPersonDto : PersonDto, IModelPerson
{
    public int BeautyCompetitionsWon { get; set; }
    public override string PersonType
    {
        get { return "Model"; }
    }
}

因此,我们创建了一个映射:

As such, we create a mapping:

Mapper.Initialize(config =>
{
    config.CreateMap<IPerson, PersonDto>()
        .Include<IModelPerson, ModelPersonDto>()
        .ConstructUsing((IPerson person) => 
        {
            if (person is IModelPerson) return new ModelPersonDto();

            throw new InvalidOperationException("Unknown person type: " + person.GetType().FullName);
        })
        ;

    config.CreateMap<IModelPerson, ModelPersonDto>();
});

所以,我在这里有两个问题.

So, I have two issues here.

1.有没有办法创建没有ConstructUsing子句的映射?我以为拥有更具体版本的CreateMap会为我们解决这个问题,但是如果我没有子句,AutoMapper告诉我无法创建抽象类的实例".

1. Is there any way of creating the mappings without the ConstructUsing clause? I thought that having the more specific version of CreateMap would have taken care of this for us, but if I don't have the ConstructUsing clause, AutoMapper tells me "Instances of abstract classes cannot be created".

2.为什么我的子类中的属性未映射?如果我按如下所示执行映射:

2. Why don't the properties from my subclasses get mapped? If I execute a mapping as follows:

var source = new ModelPersonEntity { Id = 100, BeautyCompetitionsWon = 9 };
var target = Mapper.Map<PersonDto>(source);

target.BeautyCompetitionsWon的期望值为9,但实际值为0.

The expected value for target.BeautyCompetitionsWon is 9, but the actual value is 0.

推荐答案

问题1:我不知道.

问题2:使用.ConstructUsing()时,请确保返回的是所要映射的对象,而不是一个新的实例.

Question 2: When using the .ConstructUsing() make sure you return the mapped object you are after rather than a fresh instance.

例如

Mapper.Initialize(config =>
{
    config.CreateMap<IPerson, PersonDto>()
        .Include<IModelPerson, ModelPersonDto>()
        .ConstructUsing((IPerson person) => 
        {
            if (person is IModelPerson) return Mapper.Map<ModelPersonDto>(person);

            throw new InvalidOperationException("Unknown person type: " + person.GetType().FullName);
        })
        ;

    config.CreateMap<IModelPerson, ModelPersonDto>();
});

这篇关于使用AutoMapper从接口映射到具体类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆