简体   繁体   English

使用界面的AutoMapper映射与具体映射

[英]AutoMapper mapping using interface vs concrete map

I don't think this is possible, but it's worth the question, I suppose. 我认为这是不可能的,但是我想这是值得提出的问题。

I have the following types that share an interface (I promise, this isn't the same question I've asked before). 我有以下几种共享接口的类型(我保证,这与我之前提出的问题不同)。

public interface ICustomer;

public class CustomerBO : ICustomer

public class CustomerSO : ICustomer // SO is Service Object in this case.

Then, I have the following mapping: 然后,我有以下映射:

Mapper.Map<ICustomer, ICustomer>();

Now, here's where it gets interesting / confusing. 现在,这里变得有趣/令人困惑。

This works: 这有效:

Mapper.Map<ICustomer, ICustomer>(customerSO, new CustomerBO);

This doesn't work: 这不起作用:

Mapper.Map(customerSO, new CustomerBO());

Now, normally I wouldn't have a problem with just typing in the first Map statement with the two interface type defined, but my problem is when the Customer object is buried somewhere. 现在,通常只需输入定义了两个接口类型的第一个Map语句就不会有问题,但是我的问题是,当Customer对象埋在某个地方时。

public class CustomerOrderDTO
{
    ICustomer customer;
}

public class CustomerOrderSO
{
    CustomerSO customer;
}

Mapper.Map<CustomerOrderDTO, CustomerOrderSO>();

This doesn't work, because there's no mapping from ICustomer to CustomerSO, so config assertion fails. 这是行不通的,因为没有从ICustomer到CustomerSO的映射,因此配置声明失败。

Currently, I'm going around the issue by doing this: 目前,我正在通过以下方法解决此问题:

Mapper.CreateMap<CustomerOrderDTO, CustomerOrderSO>()
    .ForMember(desc => dest.customer
        , exp => exp.MapFrom(src => Mapper.Map<ICustomer, ICustomer>(src.customer
            , new CustomerSO));

However, I would have to do this for every DTO-type object that we have, and then quite possibly have a cascading effect. 但是,我必须对我们拥有的每个DTO类型的对象执行此操作,然后很可能会产生级联效果。

I understand that technically I could do the following to resolve the issue: 我了解从技术上我可以执行以下操作来解决此问题:

Mapper.Map<CustomerBO, CustomerSO>();

However, in CustomerBO there are a lot of other properties used in the business logic not in the interface. 但是,在CustomerBO中,业务逻辑中使用的许多其他属性不在界面中。 Similarly, there are a lot of properties in CustomerSO not in the interface. 同样,CustomerSO中有很多属性不在界面中。 If I were to go with the above route, I would have a ton of Ignore() calls, and I'd have to map CustomerBO to CustomerSO, and then CustomerSO to CustomerBO, each with their own unique list of Ignore calls. 如果要采用上述路线,我将有大量的Ignore()调用,并且必须将CustomerBO映射到CustomerSO,然后将CustomerSO映射到CustomerBO,每个都有自己独特的Ignore调用列表。 Using the interfaces removes the need for the Ignore calls, as the data that I want to be visible from one to the other is defined in the interface. 使用接口消除了对Ignore调用的需求,因为在接口中定义了我希望彼此可见的数据。

So, in short, my question is this: is there some way I can tell AutoMapper to use the interface map when it encounters one of the implementing classes? 简而言之,我的问题是:当遇到一个实现类之一时,有什么方法可以告诉AutoMapper使用接口映射吗? Failing that, is there some other (read: better) way than a Map call in a MapFrom delegate to enforce my interface-to-interface mapping in a as-needed basis? 失败了,是否有其他方法(阅读:更好),而不是MapFrom委托中的Map调用来按需实施我的接口到接口映射?

In general, you'd want to configure a mapping to the ICustomer interface and override the destination type using .As<TDestination>() . 通常,您需要配置到ICustomer接口的映射,并使用.As<TDestination>()覆盖目标类型。 (Maybe this is an addition since you first asked the question.) (也许这是自您首次提出问题以来的补充内容。)

This would work for mappings between 2 layers, like your example: 这将适用于两层之间的映射,例如您的示例:

Mapper.CreateMap<CustomerDTO, ICustomer>().As<CustomerModel>();
Mapper.CreateMap<CustomerModel, ICustomer>().As<CustomerDTO>();

However, extend this to another layer, such as mapping CustomerModel to CustomerViewModel , and this falls apart. 但是,将其扩展到另一层,例如将CustomerModel映射到CustomerViewModel ,这将分崩离析。 You can only tell AutoMapper one destination type to use for instantiation. 您只能告诉AutoMapper一种用于实例化的目标类型。

But similar to the comments above, I would question the reason for having a property typed as the interface within those other classes. 但是类似于上面的评论,我会质疑在其他类中将属性键入为接口的原因。 Why should a CustomerOrderModel have a ICustomer customer property? 为什么CustomerOrderModel应该具有ICustomer customer属性? Can you replace customer with an instance of a CustomerDTO and still have your program be correct? 您可以用CustomerDTO实例替换客户,但程序仍然正确吗? If you have common behavior for objects that contain a customer, you could have those parent objects implement an interface, ICustomerAccessor . 如果您对包含客户的对象有共同的行为,则可以让这些父对象实现ICustomerAccessor接口。 Then, use explicit interface implementation to add the weaker-typed property, and it won't have to interfere with the name. 然后,使用显式接口实现来添加弱类型的属性,而不必干扰名称。

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

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