在不同情况下不同地图

时间:2016-07-26 16:13:58

标签: c# entity-framework automapper

我们将实体映射到API的模型。当一个实体是另一个实体的子实体时,我们通常使用一个只有显示名称和id的通用模型。我想做的是,如果实体是某种类型的孩子与另一种类型的孩子,则以不同方式映射该显示名称。除了专门为此目的创建新的通用模型之外,还有什么方法可以做到这一点吗?

实体示例

CompanyName {
    int Id { get; set; }
    string DisplayName { get; set; }
}

Contact {
    int Id { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    int? CompanyNameId { get; set; }
    CompanyName CompanyName { get; set; }
    string DisplayName { get {
        return string.Format("{0} {1}{2}", FirstName, LastName, CompanyName != null ? string.Format(" - {0}", CompanyName.Name) : string.Empty);
    } }
}

Employee {
    int Id { get; set; }
    int ContactId { get; set; }
    Contact Contact { get; set; }
}

模型示例

CompanyNameModel {
    int Id { get; set; }
    string DisplayName { get; set; }
}

ContactModel {
    int Id { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    int? CompanyNameId { get; set; }
    CompanyNameModel CompanyName { get; set; }
    string DisplayName { get; set; }
}

EmployeeModel {
    int Id { get; set; }
    int ContactId { get; set; }
    //XSModel Contact { get; set; } // What I'm trying to use
    XSContactNoCompanyModel Contact { get; set; }
}

XSModel {
    int Id { get; set; }
    string DisplayName { get; set; }
}

XSContactNoCompanyModel : XSModel { }

地图注册示例

Mapper.CreateMap<CompanyName, CompanyNameModel>();
Mapper.CreateMap<CompanyName, XSModel>();
Mapper.CreateMap<Contact, ContactModel>();
Mapper.CreateMap<Contact, XSModel>();
// This is my current workaround, but I'd like to get away with less models if possible.
Mapper.CreateMap<Contact, XSContactNoCompanyModel>().ForMember(x => x.DisplayName, x => x.MapFrom(y => y.FirstName + ' ' + y.LastName));
Mapper.CreateMap<Employee, EmployeeModel>();

// What I'm trying to do:
//Mapper.CreateMap<Employee, EmployeeModel>().ForMember(x => x.Contact.DisplayName, x => x.MapFrom(y => y.Contact.FirstName + ' ' + y.Contact.LastName));
// This errors with 'Expression must resolve to top-level member and not any child object's properties.'

3 个答案:

答案 0 :(得分:2)

看起来您正在尝试配置子属性,而不是AutoMapper的工作方式。创建映射时,您要配置目标类型的成员,而不是子对象。

你的陈述“我想用更少的模特逃脱”。

别。为特定配置创建特定情况的模型。这就是重点。根据这些情况和配置命名目标类型。添加额外的目标模型类型并不是一项重要的成本,但是配置复杂是一种心理成本。

答案 1 :(得分:1)

您可以使用AfterMap(或BeforeMap)来完成以下任务:

Mapper.CreateMap<Employee, EmployeeModel()
    .ForMember(dest => dest.Contact.DisplayName, config => config.Ignore())
    .AfterMap((src, dest) => 
        dest.Contact.DisplayName = src.Contact.FirstName + " " + src.Contact.LastName);

答案 2 :(得分:0)

您可以使用投影来自定义某些成员的映射:

https://github.com/AutoMapper/AutoMapper/wiki/Projection