[英]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
是我DbContext
和As
我DbSet
的A
。
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.
但是否则,我认为您需要在目的地中输入正确的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.