场景
我正在更新.NET API以对所有数据库密钥字段进行编码,以使顺序密钥不会暴露给最终用户。我为此使用hashids.org,并建立了辅助方法来快速解码/编码自动映射器映射中的属性。但是,API有多个版本,只有最新版本的API才能使用此功能进行更新,这意味着我不能简单地覆盖现有的类。我已经实现了一些可行的解决方案,但是它们都带有一种不好的代码味道,我希望清除它们。
解决方案
我目前正在控制器层执行编码。我也可以在数据访问层看到这样做的好处,但是觉得在该层存在更大的泄漏/丢失转换风险,特别是因为API有许多不同的数据源。另外,隐藏密钥是外界的问题,因为控制器是网守,所以在那里感觉很合适。
应用程序当前具有以下模型模式,无法更改:模型(数据库中存在的模型)> ValueObject(服务模型,VO)> DTO(API模型)。
((1)初始尝试
[下面是需要支持编码和解码状态的类的示例,其中Utils.Encode()
和Utils.Decode()
是将使用Hashids在int和string之间转换字段的辅助方法。
//EquipmentDTO.cs
public class EquipmentDTO //encoded class
{
public string Id {get; set;}
public string Name {get; set;}
}
public class EquipmentUnencodedDTO //decoded class
{
public int Id {get; set;}
public string Name {get; set;}
}
//Automapper.cs
CreateMap<EquipmentUnencodedDTO, EquipmentDTO>()
.ForMember(dst => dst.Id, opt => opt.MapFrom(src => Utils.Encode(src.Id)));
CreateMap<EquipmentDTO, EquipmentUnencodedDTO>()
.ForMember(dst => dst.Id, opt => opt.MapFrom(src => Utils.Decode(src.Id)));
CreateMap<EquipmentVO, EquipmentDTO>() //mapping from service model to controller model
.ForMember(dst => dst.Id, opt => opt.MapFrom(src => Utils.Encode(src.Id)));
CreateMap<EquipmentDTO, EquipmentVO>()
.ForMember(dst => dst.Id, opt => opt.MapFrom(src => Utils.Decode(src.Id)));
CreateMap<Equipment, EquipmentVO>() //mapping from DB model to service model
.ForMember(dst => dst.Id, opt => opt.MapFrom(src => src.Id));
EquipmentDTO
设为编码版本因为我希望这成为新的标准最终导致弃用和移除EquipmentUnencodedDTO
,因为旧的控制权最终得到了更新。CreateMap<EquipmentVO, EquipmentDTO>
复制为CreateMap<EquipmentVO, EquipmentUnencodedDTO>
(反之),因为这会导致AutoMapper文件中出现很多重复,已经很大了(尽管也许这不是一个真正的问题?)Mapper.Map<EquipmentVO>(Mapper.Map<EquipmentDTO>(unencodedEquipmentInput))
非常难看。CreateMap<EquipmentVO, EquipmentUnencodedDTO>
,此问题就消失了>((2)第二次尝试
上面的两个要点使我重构为:
public class EquipmentDTO
{
public string Id {get; set;}
public string Name {get; set;}
public Decoded Decode(){
return Mapper.Map<Decoded>(this);
}
public class Decoded: EquipmentDTO {
public new int Id {get; set;}
public EquipmentDTO Encode(){
return Mapper.Map<EquipmentDTO>(this);
}
}
}
// Automappers are the same, except EquipmentUnencodedDTO is now EquipmentDTO.Decoded
Mapper.Map<EquipmentVO>(unencodedEquipmentInput.Encode());
((3)下次尝试
我的下一个尝试是将已解码类的缺失映射添加到服务模型,并撤消尝试2的更改。这创建了很多重复的映射代码,我仍然在两个类中都停留在重复的属性上,而没有明确指出要解码/编码的字段,这一切都比需要的麻烦得多。
感谢您提供任何建议!
方案我正在更新我的.NET API以对所有数据库密钥字段进行编码,以使顺序密钥不会暴露给最终用户。我为此使用hashids.org,并已建立了辅助方法...
这是不能真正直接回答您问题的答案之一,但是是解决当前问题的另一种方法。根据我上面的评论。