Automapper抛出“输入字符串格式不正确”

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

我正在尝试使用自动映射器映射两个类。问题源于我的类具有已编码和未编码的状态,该状态将Id字段中的值从混淆的字符串更改为可以解析为int的字符串,但是我的印象是我正在处理正确,这样就不会出现解析问题。

即使我解码了.BeforeMap()中的状态,也仍然收到错误消息,指出输入的类型错误。

班级

public class CompanyDTO {
  public CompanyDTO(){
    IsEncoded = true;
  }

  private int id { get; set; }
  public string Id
  {
      get
      {
          return GetIdValue(id);
      }
      set
      {
          id = SetIdValue(value);
      }
  }

  public bool IsEncoded {get; private set;}

  private string GetIdValue(string v){
    return isEncoded ? Utils.EncodeParam(v) : v.ToString(); // EncodeParam() performs encoding algorithm
  }

  private void SetIdValue(string v) {
    var intValue = v.TryParseInt(-1); // TryParseInt() custom extension to parse string to int else return parameter (-1)
    return intValue == -1 ? Utils.DecodeParam(v) : intValue; // DecodeParam() performs decoding algorithm
  }
}

public class CompanyVO {
  public CompanyVO() {}
  public CompanyVO(int id) {
    Id = id;
  }
  public int Id {get; set;}
}

映射器

CreateMap<CompanyDTO, CompanyVO>()
  .BeforeMap((src, dst) => Utils.DecodeState(src)) // DecodeState() toggles IsEncoded to false
  .ForMember(dst => dst.Id, opt => opt.MapFrom(src => src.Id); // will automatically convert string src.Id to int

CreateMap<CompanyVO, CompanyDTO>()
  .ForMember(dst => dst.Id, opt => opt.MapFrom(src => src.Id.ToString());

实施

public void AddCompany(CompanyDTO company) {
  Mapper.Map<CompanyVO>(company); // Error: Input string was not in a correct format
  ...
}
c# constructor automapper
1个回答
0
投票

问题是自动映射器使用了错误的构造函数,您必须通过在映射配置中使用.ConstructUsing()指定要使用的构造函数。

这是自动映射器执行的事件的当前顺序:

  1. 在目标类型上运行构造函数(不确定自动映射器如何选择要运行的那个)
public CompanyVO(int id) { // Error: passed id is the encoded string, not the decoded version and not an int
  Id = id;
}
  1. 运行.BeforeMap()
  2. 运行映射器

可以通过指定在自动映射器中使用哪个构造函数来解决该错误。

CreateMap<CompanyDTO, CompanyVO>()
  .BeforeMap((src, dst) => Utils.DecodeState(src))
  .ConstructUsing(src => new CompanyVO()) // set constructor to the parameter-less one
  .ForMember(dst => dst.Id, opt => opt.MapFrom(src => src.Id);

我的用例允许我不带任何参数地使用构造器,尽管我也可以很容易地做到这一点:

CreateMap<CompanyDTO, CompanyVO>()
  .ConstructUsing(src => {
    Utils.DecodeState(src)
    return new CompanyVO(src.Id.TryParseInt(-1))
  })
  .ForMember(dst => dst.Id, opt => opt.MapFrom(src => src.Id);
© www.soinside.com 2019 - 2024. All rights reserved.