在不同情况下以不同方式映射
Map Differently in Different Circumstances
我们为 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.'
您可以使用投影为特定成员自定义映射:
您可以使用 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);
看起来您正在尝试配置子 属性,这不是 AutoMapper 的工作方式。创建地图时,您是在配置目标类型的成员,而不是子对象。
你的声明"I'd like to get away with fewer models".
不要。为特定配置的特定情况创建模型。这就是重点。根据这些情况和配置命名目标类型。添加额外的目标模型类型并不是很大的成本,但复杂的配置是一种心理成本。
我们为 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.'
您可以使用投影为特定成员自定义映射:
您可以使用 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);
看起来您正在尝试配置子 属性,这不是 AutoMapper 的工作方式。创建地图时,您是在配置目标类型的成员,而不是子对象。
你的声明"I'd like to get away with fewer models".
不要。为特定配置的特定情况创建模型。这就是重点。根据这些情况和配置命名目标类型。添加额外的目标模型类型并不是很大的成本,但复杂的配置是一种心理成本。