如何将不同源类型映射为多个输出类共用的同一复杂类型属性
如何实现多输入类到CountryAndCity属性的映射?
嘿,这个场景在日常.NET开发里太常见了!我给你分享几个实用的实现思路,你可以根据项目的复杂度和团队习惯来选:
1. 手动映射(适合简单场景)
如果你的输入类数量不多、映射逻辑也不复杂,手动写映射逻辑是最直接的——没有额外依赖,调试起来也简单。你可以写一个专门的映射辅助类,或者给输入类扩展映射方法:
先假设你有两个典型的输入类:
public class InputClassX { public string CountryName { get; set; } public string CityName { get; set; } public string ZipCodeValue { get; set; } } public class InputClassY { public string CountryCode { get; set; } public string CityId { get; set; } public string PostalCode { get; set; } }
然后写一个静态映射辅助类:
public static class CountryAndCityMapper { // 从InputClassX映射到CountryAndCity public static CountryAndCity MapToCountryAndCity(this InputClassX input) { if (input == null) return null; return new CountryAndCity { Country = new Country { Name = input.CountryName }, // 假设Country类有Name属性 City = new City { Name = input.CityName }, // 假设City类有Name属性 ZipCode = new ZipCode { Value = input.ZipCodeValue } // 假设ZipCode类有Value属性 }; } // 从InputClassY映射到CountryAndCity public static CountryAndCity MapToCountryAndCity(this InputClassY input) { if (input == null) return null; return new CountryAndCity { Country = new Country { Code = input.CountryCode }, City = new City { Id = input.CityId }, ZipCode = new ZipCode { Value = input.PostalCode } }; } }
使用的时候就非常简洁:
var inputX = new InputClassX { CountryName = "China", CityName = "Beijing", ZipCodeValue = "100000" }; var outputA = new OutputClassA { CountryAndCity = inputX.MapToCountryAndCity() }; var inputY = new InputClassY { CountryCode = "CN", CityId = "BJ", PostalCode = "100000" }; var outputB = new OutputClassB { CountryAndCity = inputY.MapToCountryAndCity() };
2. 使用AutoMapper(适合复杂/多类场景)
如果你的输入类数量多、映射规则有重复,用AutoMapper这种成熟的映射库能帮你省大量重复代码。
首先安装AutoMapper的NuGet包:
Install-Package AutoMapper
然后创建映射配置类:
public class CountryCityMappingProfile : Profile { public CountryCityMappingProfile() { // 配置InputClassX到CountryAndCity的映射规则 CreateMap<InputClassX, CountryAndCity>() .ForMember(dest => dest.Country, opt => opt.MapFrom(src => new Country { Name = src.CountryName })) .ForMember(dest => dest.City, opt => opt.MapFrom(src => new City { Name = src.CityName })) .ForMember(dest => dest.ZipCode, opt => opt.MapFrom(src => new ZipCode { Value = src.ZipCodeValue })); // 配置InputClassY到CountryAndCity的映射规则 CreateMap<InputClassY, CountryAndCity>() .ForMember(dest => dest.Country, opt => opt.MapFrom(src => new Country { Code = src.CountryCode })) .ForMember(dest => dest.City, opt => opt.MapFrom(src => new City { Id = src.CityId })) .ForMember(dest => dest.ZipCode, opt => opt.MapFrom(src => new ZipCode { Value = src.PostalCode })); } }
在项目启动时初始化AutoMapper(以ASP.NET Core为例,在Program.cs中):
var builder = WebApplication.CreateBuilder(args); // 注册AutoMapper builder.Services.AddAutoMapper(typeof(CountryCityMappingProfile));
最后在业务代码中注入IMapper使用:
public class DataConversionService { private readonly IMapper _mapper; public DataConversionService(IMapper mapper) { _mapper = mapper; } public OutputClassA ConvertToOutputA(InputClassX input) { return new OutputClassA { CountryAndCity = _mapper.Map<CountryAndCity>(input) }; } public OutputClassB ConvertToOutputB(InputClassY input) { return new OutputClassB { CountryAndCity = _mapper.Map<CountryAndCity>(input) }; } }
3. 泛型反射映射(进阶玩法)
如果你的所有输入类都遵循统一的命名规则(比如所有国家字段都叫CountryXXX),可以用反射写一个泛型映射方法来减少重复代码。不过反射会有轻微性能损耗,适合规则高度统一的场景,这里就不展开细说了——毕竟手动映射和AutoMapper已经能覆盖90%以上的日常需求。
内容的提问来源于stack exchange,提问作者Omtechguy
相关产品推荐
相关产品推荐

