XML转对象生成CSV前,多条件属性值映射转换的最优方案咨询
问题描述
现有一个Mapper类,定义如下:
public class Mapper { [Display(Name="MapName")] public string Name { get; set; } [Display(Name="MapType")] public string Type { get; set; } }在将该对象数据生成CSV格式前,需根据源值进行属性值映射转换,例如将Name属性值"xyz"转为"a"、"abc"转为"123",此类映射条件约有10-15个,请问是否有合适的实现方案?
可行的实现方案
嘿,这个需求其实挺常见的,针对10-15个映射规则的场景,我给你几个不同复杂度的方案,你可以根据自己的维护需求和扩展性要求来选:
方案一:字典映射(最快速易实现)
这是最直接的方式,用字典存储键值对映射,转换时直接查表。优点是代码简单、性能好,适合映射规则固定、不需要频繁修改的场景。
实现步骤:
- 定义一个静态字典存储Name的映射规则(如果Type也需要映射,可以再建一个独立字典)
- 在转换为CSV前,调用方法用字典替换属性值
示例代码:
// 定义全局映射字典(可以放在工具类里) private static readonly Dictionary<string, string> _nameMappings = new Dictionary<string, string> { {"xyz", "a"}, {"abc", "123"}, // 补充剩余的8-13个映射规则... }; // 属性值转换方法 public string GetMappedName(string originalName) { // 存在映射则返回转换后的值,否则返回原字符串(也可以根据需求抛出异常) return _nameMappings.TryGetValue(originalName, out var mappedValue) ? mappedValue : originalName; } // 实际使用示例 var mapper = new Mapper { Name = "abc", Type = "SampleType" }; var mappedName = GetMappedName(mapper.Name); // 后续用mappedName生成CSV内容即可
方案二:策略模式(适合复杂逻辑或未来扩展)
如果后续你的映射规则可能变得更复杂(比如需要结合多个属性判断、或者需要切换不同的映射规则组),策略模式会更灵活。把不同的映射逻辑封装成独立策略类,方便后续扩展和维护。
实现步骤:
- 定义通用的映射策略接口
- 实现针对Name属性的具体映射策略类
- 实例化策略类并完成转换
示例代码:
// 定义映射策略接口 public interface IMappingStrategy<T> { T Map(T originalValue); } // 针对Name属性的具体映射策略 public class NameMappingStrategy : IMappingStrategy<string> { private readonly Dictionary<string, string> _mappings = new Dictionary<string, string> { {"xyz", "a"}, {"abc", "123"}, // 其他映射规则... }; public string Map(string originalValue) { return _mappings.TryGetValue(originalValue, out var mapped) ? mapped : originalValue; } } // 使用示例 var nameMappingStrategy = new NameMappingStrategy(); var mapper = new Mapper { Name = "xyz" }; var mappedName = nameMappingStrategy.Map(mapper.Name);
这种方式的好处是,以后如果要给Type属性加映射规则,或者修改Name的映射逻辑,只需要新增/修改对应的策略类即可,完全不用改动原有业务代码,符合开闭原则。
方案三:自定义Attribute(优雅但稍复杂)
如果你想把映射规则和属性直接绑定在一起,让代码逻辑更直观,可以自定义一个MappingAttribute,把映射规则标记在属性上。
实现步骤:
- 自定义一个用于存储映射规则的Attribute
- 在Mapper类的对应属性上标记该Attribute,配置所有映射规则
- 通过反射读取Attribute中的映射规则,完成值转换
示例代码:
// 自定义映射Attribute [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] public class MappingAttribute : Attribute { public string OriginalValue { get; } public string MappedValue { get; } public MappingAttribute(string originalValue, string mappedValue) { OriginalValue = originalValue; MappedValue = mappedValue; } } // 修改Mapper类,添加映射Attribute public class Mapper { [Display(Name="MapName")] [Mapping("xyz", "a")] [Mapping("abc", "123")] // 补充其他映射规则... public string Name { get; set; } [Display(Name="MapType")] public string Type { get; set; } } // 通用转换方法,通过反射读取映射规则 public string GetMappedValue(object obj, string propertyName) { var property = obj.GetType().GetProperty(propertyName); if (property == null) return null; var originalValue = property.GetValue(obj) as string; if (string.IsNullOrEmpty(originalValue)) return originalValue; var mappings = property.GetCustomAttributes<MappingAttribute>(); var targetMapping = mappings.FirstOrDefault(m => m.OriginalValue == originalValue); return targetMapping?.MappedValue ?? originalValue; } // 使用示例 var mapper = new Mapper { Name = "abc" }; var mappedName = GetMappedValue(mapper, nameof(Mapper.Name));
这种方式的优点是映射规则和属性紧密关联,代码可读性高,但因为用到了反射,性能会比字典映射稍差一点——不过10-15个映射的场景下,这点性能差异完全可以忽略不计。
内容的提问来源于stack exchange,提问作者Vicky
相关产品推荐
相关产品推荐

