如何基于两个C#源类更优雅地创建符合属性映射要求的自定义对象
从两个C#类数据源生成组合自定义对象的实现方案
注意:你提供的类A构造函数中有拼写错误,
LasetName = lastName应为LastName = lastName,否则初始化时会报错。
你当前的写法在属性量少的时候可以正常运行,但当属性数量较多时,映射逻辑会散落在业务代码各处,修改字段映射规则时需要逐一修改调用点,维护成本很高,这里提供几种可维护性更高的实现方案,适配不同的业务场景:
方案1:自定义类封装静态工厂方法(最推荐,无第三方依赖)
把所有映射逻辑集中封装在目标Custom类中,后续修改映射规则只要调整一处即可,还可以统一添加参数非空校验、属性冲突处理(例如A和B的LastName不一致时的取值逻辑)等通用逻辑。
public class Custom { // 原有构造函数 public Custom(string lastName, string firstName, string street, string city, int shoeSize) { LastName = lastName; FirstName = firstName; Street = street; City = city; ShoeSize = shoeSize; } // 新增静态工厂方法,统一处理A、B到Custom的映射 public static Custom CreateFromAB(A sourceA, B sourceB) { // 可在这里添加参数非空校验、属性一致性校验等逻辑 if (sourceA == null) throw new ArgumentNullException(nameof(sourceA)); if (sourceB == null) throw new ArgumentNullException(nameof(sourceB)); return new Custom( lastName: sourceA.LastName, firstName: sourceA.FirstName, street: sourceA.Street, city: sourceB.City, shoeSize: sourceB.ShoeSize ); } public string LastName { get; set; } public string FirstName { get; set; } public string Street { get; set; } public string City { get; set; } public int ShoeSize { get; set; } }
业务侧调用代码非常简洁:
var a = new A("dd", "afafd", "asdf","adf"); var b = new B("dd", "afafd", "asdf","adf",22); var custom = Custom.CreateFromAB(a, b);
方案2:扩展方法实现(适配无法修改Custom类定义的场景)
如果因为权限、依赖层级等原因不能修改Custom类的源码,可以通过扩展方法封装映射逻辑:
// 放在单独的映射扩展类中,避免污染源类定义 public static class MappingExtensions { public static Custom ToCustom(this A sourceA, B sourceB) { if (sourceA == null) throw new ArgumentNullException(nameof(sourceA)); if (sourceB == null) throw new ArgumentNullException(nameof(sourceB)); return new Custom( sourceA.LastName, sourceA.FirstName, sourceA.Street, sourceB.City, sourceB.ShoeSize ); } }
业务侧调用方式:
var custom = a.ToCustom(b);
方案3:对象映射库实现(适配属性量极大、映射规则复杂的场景)
如果两个源类的属性数量非常多(几十上百个),手动写映射代码重复工作量大,可以使用AutoMapper这类成熟的对象映射库,通过配置约定减少重复代码,同名属性可以默认自动映射,不需要逐一配置。
映射配置示例:
// 全局只需要配置一次 var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<(A a, B b), Custom>() // 非同名/非默认映射规则单独配置,同名属性自动映射 .ForMember(dest => dest.City, opt => opt.MapFrom(src => src.b.City)) .ForMember(dest => dest.ShoeSize, opt => opt.MapFrom(src => src.b.ShoeSize)); }); var mapper = mapperConfig.CreateMapper();
业务侧调用:
var custom = mapper.Map<Custom>((a, b));
内容的提问来源于stack exchange,提问作者Dario M.
相关产品推荐
相关产品推荐

