如何处理同一C#类的编码和解码版本

问题描述 投票:1回答:1

场景

我正在更新.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文件中出现很多重复,已经很大了(尽管也许这不是一个真正的问题?)
  • 我不喜欢这种解决方案,因为在我的旧控制器中,映射现在令人困惑。例如,在POST中,必须通过以下命令将未编码的输入DTO转换为服务模型: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,并已建立了辅助方法...

c# inner-classes api-design clean-architecture hashids
1个回答
0
投票

这是不能真正直接回答您问题的答案之一,但是是解决当前问题的另一种方法。根据我上面的评论。

© www.soinside.com 2019 - 2024. All rights reserved.