简体   繁体   English

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

[英]Use AutoMapper to use map of derived object instead of parent object

I can't figure a solution to my problem using AutoMapper nor find right keywords to find a solution online, hence the maybe bad title for that question, here is my problem: 我无法使用AutoMapper找到解决问题的方法,也找不到合适的关键字来在线查找解决方案,因此该问题的标题可能不好,这是我的问题:

I'd like to force AutoMapper to use one map out of two valid maps. 我想强迫AutoMapper使用两个有效地图中的一个地图。 Here an exemple: 这是一个例子:

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));
    }
}

If I remove below line, AutoMapper throws an error saying that it can't find a valid map for B property in A to ADTO map. 如果我删除以下行,则AutoMapper会引发错误,指出它无法在A到ADTO映射中为B属性找到有效的映射。

Mapper.CreateMap<B, BDTO>();

Is there any way to make my map B to CDTO valid for it ? 有什么方法可以使我的地图B到CDTO有效吗?

EDIT from Lucian answer 卢西安答案的编辑

So I guess one solution is to make it two steps : 所以我想一种解决方案是使它成为两个步骤:

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

I'm more into one proper line solution : 我更喜欢一种合适的解决方案:

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

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

Any way to make it happen ? 有什么办法可以实现?

EDIT 2 from Lucian answer again 来自Lucian的EDIT 2再次回答

The fact is that A and B are entities coming from EF and that I don't have access to ADTO initialization as I use .ProjectTo extension. 事实是,A和B是来自EF的实体,由于我使用.ProjectTo扩展名,因此我无权访问ADTO初始化。

My code is something more like: 我的代码更像是:

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

Where db is my DbContext and As my DbSet of A . 其中db是我DbContextAsDbSetA

EDIT 3 from Lucian answer again 来自Lucian的EDIT 3再次回答

I did not know about that ConstructProjectionUsing method, thanks for that! 我不知道那个ConstructProjectionUsing方法,谢谢! Here the code I manage to build with your answer. 在这里,我设法用您的答案构建代码。

Mapper.CreateMap<A, ADTO>()
   .ConstructProjectionUsing(a => new ADTO() { B = new CDTO() })
   .ForMember(adto => adto.B, opt => opt.MapFrom(a => a.B));

And that's brillant! 那太好了! But now, I have another problem, B and BDTO are in fact ICollection and IEnumerable... I didn't think it will be a problem so I didn't tell. 但是现在,我还有另一个问题,B和BDTO实际上是ICollection和IEnumerable ...我不认为这会是一个问题,所以我没有告诉。 Here the updated code: 这里是更新的代码:

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

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

So I think I can't use the ConstructProjectionUsing as this code won't compile: 所以我认为我不能使用ConstructProjectionUsing,因为此代码无法编译:

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));

I guess I'm stuck here ? 我想我被困在这里了吗?

You can initialize ADTO.B with an instance of CDTO and map to an existing object. 您可以使用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

This would work with a newer AM. 这将适用于较新的AM。 You might need UseDestinationValue with older ones. 您可能需要将UseDestinationValue和旧的一起使用。

For construction you can use ConstructProjectionUsing. 对于构造,可以使用ConstructProjectionUsing。 An example . 一个例子 But otherwise, I think you need the right type in the destination. 但是否则,我认为您需要在目的地中输入正确的类型。

OK, so As is what allows you to redirect the map. 好的,按原样,您可以重定向地图。 And it seems to work with ProjectTo. 它似乎可以与ProjectTo一起使用。 See here . 这里

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

Of course this applies everywhere, not only for ProjectTo. 当然,这适用于所有地方,不仅适用于ProjectTo。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM