使用AutoMapper来使用派生对象的映射而不是父对象

时间:2017-08-02 07:38:29

标签: c# inheritance automapper

我无法使用AutoMapper找到问题的解决方案,也找不到合适的关键字来在线找到解决方案,因此这个问题的标题可能不错,这是我的问题:

我想强制AutoMapper使用两张有效地图中的一张地图。这是一个例子:

public class A
{
    public B B { get; set; }
}

public class ADTO
{
    public BDTO B { get; set; }
}

public class B
{
}

public class BDTO
{
}

public class CDTO : BDTO
{
}

public class AProfile : Profile
{
    public AProfile()
    {
        Mapper.CreateMap<B, BDTO>();
        Mapper.CreateMap<B, CDTO>();

        // Is there a way to force AutoMapper to use B to CDTO instead of B to BDTO ?
        Mapper.CreateMap<A, ADTO>()
            .ForMember(adto => adto.B, opt => opt.MapFrom(a => a.B));
    }
}

如果我删除以下行,AutoMapper会抛出一个错误,指出它无法在A到ADTO地图中找到B属性的有效地图。

Mapper.CreateMap<B, BDTO>();

有没有办法让我的地图B到CDTO有效?

来自Lucian回复的编辑

所以我想一个解决方案就是分两步:

var a = new A { B = new B() }
var adto = new ADTO();

adto = Mapper.Map(a, adto); // Map B to BDTO
adto.B = Mapper.Map<CDTO>(a.B); // Change BDTO to CDTO

我在一个正确的解决方案中更多:

var a = new A { B = new B() }
var adto = new ADTO();

adto = Mapper.Map(a, adto); // Map directly B to CDTO

有什么方法可以实现吗?

来自Lucian的EDIT 2再次回答

事实是,A和B是来自EF的实体,当我使用.ProjectTo扩展时,我无法访问ADTO初始化。

我的代码更像是:

var adto = db.As.ProjectTo<ADTO>().ToList();

db DbContext As DbSet A Mapper.CreateMap<A, ADTO>() .ConstructProjectionUsing(a => new ADTO() { B = new CDTO() }) .ForMember(adto => adto.B, opt => opt.MapFrom(a => a.B)); 。{/ p>

来自Lucian的EDIT 3再次回答

我不知道那个ConstructProjectionUsing方法,谢谢!这是我用你的答案建立的代码。

public class A
{
    public ICollection<B> B { get; set; }
}

public class ADTO
{
    public IEnumerable<BDTO> B { get; set; }
}

这就是明智的!但是现在,我还有另外一个问题,B和BDTO实际上是ICollection和IEnumerable ......我不认为这将是一个问题,所以我没有告诉。这里更新了代码:

Mapper.CreateMap<A, ADTO>()
   .ConstructProjectionUsing(a => new ADTO() { B = new List<CDTO>() }) // Error here, can't convert List<CDTO> to List<BDTO> 
   .ForMember(adto => adto.B, opt => opt.MapFrom(a => a.B));

所以我认为我不能使用ConstructProjectionUsing,因为这段代码不会编译:

Object{ 2017-08-01:Array(2), 2017-08-02:Array(1) }

我想我会被困在这里?

3 个答案:

答案 0 :(得分:1)

您可以使用CDTO实例初始化ADTO.B并映射到现有对象。

var a = new A { B = new B() };  
var adto = new ADTO { B = new CDTO() };  
Mapper.Map(a, adto); // Map directly B to CDTO

这适用于较新的AM。您可能需要将UseDestinationValue与旧版本一起使用。

答案 1 :(得分:1)

对于构造,您可以使用ConstructProjectionUsing。 An example。但除此之外,我认为您需要在目的地中使用正确的类型。

答案 2 :(得分:1)

好的,所以这是允许你重定向地图的原因。它似乎与ProjectTo一起使用。请参阅here

 Mapper.CreateMap<B, BDTO>().As<CDTO>();

当然这适用于所有地方,不仅适用于ProjectTo。