多层架构下多模型序列化与类型映射的可维护性优化咨询
解决方案
针对多层多态模型映射重复、序列化反序列化需频繁修改的问题,推荐以下优化方案:
一、用策略模式+依赖注入重构跨层映射逻辑
核心思路是把每种动物类型的映射逻辑封装成独立策略类,通过DI容器自动管理这些策略,彻底消除重复的switch/case判断,新增类型时仅需添加对应策略类即可。
实现步骤:
- 定义通用映射接口:
public interface IAnimalMapper<TDbModel, TDto> where TDbModel : IAnimalDb where TDto : IAnimal { TDto Map(TDbModel dbModel); }
- 为每种动物实现具体映射策略:
public class DogMapper : IAnimalMapper<DogDb, DogDto> { public DogDto Map(DogDb dbModel) { return new DogDto { BarkVolume = dbModel.BarkVolume, Breed = dbModel.Breed // 映射狗的其他专属属性 }; } } public class CatMapper : IAnimalMapper<CatDb, CatDto> { public CatDto Map(CatDb dbModel) { return new CatDto { PurrIntensity = dbModel.PurrIntensity, LitterboxType = dbModel.LitterboxType // 映射猫的其他专属属性 }; } }
- 封装映射服务,通过DI获取对应策略:
public class AnimalMappingService { private readonly IServiceProvider _serviceProvider; public AnimalMappingService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IAnimal Map(IAnimalDb dbModel) { var mapperType = typeof(IAnimalMapper<,>).MakeGenericType(dbModel.GetType(), typeof(IAnimal)); dynamic mapper = _serviceProvider.GetService(mapperType); return mapper.Map((dynamic)dbModel); } }
- 在DI容器中注册所有映射策略:
// Program.cs 或 Startup.cs 中 services.AddScoped<IAnimalMapper<DogDb, DogDto>, DogMapper>(); services.AddScoped<IAnimalMapper<CatDb, CatDto>, CatMapper>(); services.AddScoped<AnimalMappingService>();
后续修改原有扩展方法,直接注入AnimalMappingService调用即可,新增动物类型时仅需添加对应的Mapper类并注册,无需修改任何原有映射逻辑。
二、优化System.Text.Json多态序列化/反序列化
放弃手动编写自定义转换器,利用System.Text.Json内置的多态配置,结合JsonDerivedType特性实现自动序列化反序列化,新增类型时仅需添加特性标记。
实现示例:
- 在根接口上添加派生类型标记:
[JsonDerivedType(typeof(DogQueueModel), typeDiscriminator: AnimalQueueType.Dog)] [JsonDerivedType(typeof(CatQueueModel), typeDiscriminator: AnimalQueueType.Cat)] public interface IAnimalQueueModel { AnimalQueueType Type { get; } } public enum AnimalQueueType { Dog, Cat } public class DogQueueModel : IAnimalQueueModel { public AnimalQueueType Type => AnimalQueueType.Dog; // 狗的专属属性 } public class CatQueueModel : IAnimalQueueModel { public AnimalQueueType Type => AnimalQueueType.Cat; // 猫的专属属性 }
- 序列化/反序列化时直接使用默认配置:
// 序列化 var dogQueueModel = new DogQueueModel(); string json = JsonSerializer.Serialize<IAnimalQueueModel>(dogQueueModel); // 反序列化 IAnimalQueueModel model = JsonSerializer.Deserialize<IAnimalQueueModel>(json);
新增动物类型时,仅需在IAnimalQueueModel上添加[JsonDerivedType]特性并实现对应模型类,无需修改转换器代码。
三、使用AutoMapper简化映射代码
如果不想手动编写映射逻辑,可利用AutoMapper的多态映射配置自动处理不同类型的映射,同时结合DI管理映射配置。
配置示例:
public class AnimalProfile : Profile { public AnimalProfile() { CreateMap<IAnimalDb, IAnimal>() .Include<DogDb, DogDto>() .Include<CatDb, CatDto>(); CreateMap<DogDb, DogDto>(); CreateMap<CatDb, CatDto>(); } }
注册AutoMapper并使用:
services.AddAutoMapper(typeof(AnimalProfile)); // 在需要映射的类中注入IMapper public class SomeService { private readonly IMapper _mapper; public SomeService(IMapper mapper) { _mapper = mapper; } public AnimalResponse ToDto(AnimalReadModel dbModel) { return new AnimalResponse { Animal = _mapper.Map<IAnimal>(dbModel.Animal) }; } }
新增类型时仅需在Profile中添加对应的Include和CreateMap配置,无需修改业务代码。
内容的提问来源于stack exchange,提问作者trinny
相关产品推荐
相关产品推荐

