如何通过AutoMapper根据配置生成不同内容的目标FHIR对象?
解决方案
针对你的场景,有几个实用的AutoMapper方案可以实现根据系统版本动态调整FHIR对象内容,以下是具体实现方式:
1. 使用AutoMapper上下文传递版本参数(最直接)
AutoMapper支持通过ResolutionContext传递自定义参数,你可以在映射时传入系统版本标识,然后在映射配置里根据这个参数分支处理逻辑,完美解决Profile无法直接访问外部配置的问题。
配置映射规则
在你的Profile类中,通过context.Items获取版本参数,针对需要差异化处理的字段设置条件逻辑:
public class InternalToFhirProfile : Profile { public InternalToFhirProfile() { CreateMap<InternalPatient, Patient>() // 普通字段保持原有映射 .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.PatientId)) // 差异化字段:根据版本设置不同值 .ForMember(dest => dest.Identifier, opt => opt.MapFrom((src, dest, _, context) => { var systemVersion = context.Items["SystemVersion"] as string; if (systemVersion == "v2") { // 新版本系统要求的Identifier格式 return new List<Identifier> { new Identifier { System = "new-system-id", Value = src.PatientId } }; } else { // 旧版本原有格式 return new List<Identifier> { new Identifier { System = "old-system-id", Value = src.PatientId } }; } })) // 也可以在Before/AfterMapping中使用上下文参数 .AfterMapping((src, dest, context) => { var systemVersion = context.Items["SystemVersion"] as string; if (systemVersion == "v2") { // 新版本需要额外填充的字段 dest.Active = true; dest.Meta = new Meta { LastUpdated = DateTimeOffset.Now }; } }); } }
执行映射时传入版本参数
在调用Map方法时,通过MappingOperationOptions传入版本标识:
// 获取系统版本(从配置/服务中读取) var systemVersion = _configuration["SystemVersion"]; // 映射时传入参数 var fhirPatient = _mapper.Map<Patient>(internalPatient, opt => opt.Items["SystemVersion"] = systemVersion);
你之前用Before/AfterMapping出错,大概率是没正确通过上下文传递参数,或者在处理时访问了未完成映射的字段,用这种方式可以确保参数正确传递,逻辑更可控。
2. 注入版本配置到自定义值解析器(适合复杂逻辑)
如果差异化逻辑比较复杂,或者需要复用多个映射规则,可以创建依赖系统版本的自定义值解析器,通过依赖注入把系统配置传入解析器:
自定义值解析器
public class FhirIdentifierResolver : IValueResolver<InternalPatient, Patient, List<Identifier>> { private readonly string _systemVersion; // 注入系统配置(或者版本服务) public FhirIdentifierResolver(IConfiguration configuration) { _systemVersion = configuration["SystemVersion"]; } public List<Identifier> Resolve(InternalPatient source, Patient destination, List<Identifier> destMember, ResolutionContext context) { if (_systemVersion == "v2") { return new List<Identifier> { new Identifier { System = "new-system-id", Value = source.PatientId } }; } else { return new List<Identifier> { new Identifier { System = "old-system-id", Value = source.PatientId } }; } } }
在Profile中使用解析器
public class InternalToFhirProfile : Profile { public InternalToFhirProfile() { CreateMap<InternalPatient, Patient>() .ForMember(dest => dest.Identifier, opt => opt.MapFrom<FhirIdentifierResolver>()); } }
注册解析器到DI容器
确保在Startup/Program中注册解析器:
services.AddSingleton<FhirIdentifierResolver>();
这种方式的好处是不用每次映射都传参数,解析器自动从配置中读取版本,适合全局统一版本的场景。
3. 条件映射规则(针对特定字段)
如果只有少数字段需要差异化,可以直接用AutoMapper的条件映射,结合上下文参数控制映射规则是否生效:
public class InternalToFhirProfile : Profile { public InternalToFhirProfile() { CreateMap<InternalPatient, Patient>() // 旧版本映射规则 .ForMember(dest => dest.Meta, opt => opt.MapFrom(src => new Meta { LastUpdated = src.CreatedDate })) // 新版本覆盖旧规则,只有当版本为v2时生效 .ForMember(dest => dest.Meta, opt => { opt.Condition((src, dest, _, context) => context.Items["SystemVersion"] as string == "v2"); opt.MapFrom(src => new Meta { LastUpdated = DateTimeOffset.Now, VersionId = "1" }); }); } }
总结
- 如果系统版本是动态变化的(比如每个请求可能不同),优先用上下文参数的方式,灵活传递版本标识。
- 如果版本是全局固定的(比如整个服务对应一个系统版本),用注入解析器的方式更简洁。
- 少数字段差异化的场景,用条件映射最轻便。
内容的提问来源于stack exchange,提问作者shortstuff
相关产品推荐
相关产品推荐

