【问题标题】:Automapper: Convert an int to a stringAutomapper:将 int 转换为字符串
【发布时间】:2013-09-15 19:54:28
【问题描述】:

我目前在我的 c# MVC 项目中使用 AutoMapper,并且遇到了从整数转换为字符串的问题。

我有两个班级:

public class Job
{
    public string Prefix { get; set; }
    public int JobNumber { get; set; }
    public int Year { get; set }
    public int JobPriority { get; set; }

    public virtual EntityPriority EntityPriority { get; set; }
}

public class JobViewModel
{
    public string JobNumberFull { get; set; }
{

使用 Automapper 我想将 Job 类中的所有三个属性连接起来形成一个字符串,然后将其映射到 JobViewModel 类中的 JobNumberFull。:

前缀-JobNumber-Year

首先我保持简单,没有将字段连接成一个字符串,我只是尝试获取 JobNumber (int) 并将其映射到 JobNumberFull (string),如下所示:

Mapper.CreateMap<int, string>().ConvertUsing(Convert.ToString);
Mapper.CreateMap<Job, JobViewModel>()
    .ForMember(d => d.JobPriorityId, opt => opt.MapFrom(s => s.EntityPriority.EntityPriorityID))
    .ForMember(d => d.JobPriorityLevel, opt => opt.MapFrom(s => s.EntityPriority.PriorityLevel))
    .ForMember(d => d.JobNumberFull, opt => opt.MapFrom(s => s.JobNumberYear));
Mapper.AssertConfigurationIsValid();

var jobsList = db.Jobs.Where(j => j.OperationID == operationId).Project().To<JobViewModel>().ToList();

当我运行它时,我得到以下错误

Type 'System.String' does not have a default constructor

我知道这是为了

Convert.ToString

但我不知道该怎么办!从字符串转换为 int 时,我可以执行 Convert.ToInt32 ,它就像一种享受。我需要创建自定义类型转换器吗?

我将如何获取字符串 prefix-jobnumber-year?

非常感谢所有帮助。


更新

感谢 Jeremy 和 AutoMapper 网站的帮助,我设法让这个工作在这里是我的解决方案,如果您认为有更优雅的解决方案,请随时发表评论:

public class Job 
{
    public string Prefix { get; set; }
    public int JobNumber { get; set; }
    public int Year { get; set; }
    public int JobPriority { get; set; }

    public virtual EntityPriority EntityPriority { get; set; }
}

public class JobViewModel 
{
    public int JobNumber { get; set; }
    public int Year { get; set; }
    public string JobNumberFull { get; set; }
}

public enum EntityPriority 
{
  Normal = 0,
  High
}

public interface IValueResolver
{
   ResolutionResult Resolve(ResolutionResult source);
}

public class JobNumberConverter : ValueResolver<Job, string>
{
    protected override string ResolveCore(Job source)
    {
        return string.Format("{0}-{1}-{2}", source.Prefix, source.JobNumber, source.Year);
    }
}

public ActionResult Index()
{
    Mapper.CreateMap<Job, JobViewModel>()
        .ForMember(jvm => jvm.JobNumberFull, opt => opt.ResolveUsing<JobNumberConverter>());
    Mapper.AssertConfigurationIsValid();

    List<Job> jobs = new List<Job>();

    Job j = new Job()
    {
        JobNumber = 1,
        Prefix = "prefix",
        Year = 2013,
        EntityPriority = EntityPriority.High,
        JobPriority = 2
    };

    Job j2 = new Job()
    {
        JobNumber = 2,
        Prefix = "prefix",
        Year = 2013,
        EntityPriority = EntityPriority.High,
        JobPriority = 2
    };

    Job j3 = new Job()
    {
        JobNumber = 3,
        Prefix = "prefix",
        Year = 2013,
        EntityPriority = EntityPriority.High,
        JobPriority = 2
    };

    jobs.Add(j);
    jobs.Add(j2);
    jobs.Add(j3);

    var jobViewModels = jobs.Select(job => Mapper.Map<JobViewModel>(job));

    return View();

}

【问题讨论】:

  • 如果你不尝试这么简化,只指定一个Job到JobViewModel的转换函数,那就简单多了。 Please read about the XY Problem 并避免在您的下一个问题中使用它。 :)
  • 还有一点需要注意 - 投影实际上会创建一个 LINQ 查询以提供给 EF。使用 Resolvers 或 ConvertUsing,LINQ 查询中不使用这些,只有 MapFrom 使用。一个快速的解决方法是简单地执行 ToString()。在您的 JobNumberFull 中,使用 MapFrom - 但使用字符串连接而不是 string.Format(EF 不知道 string.Format)。这将为您创建一个自定义 SQL 查询!

标签: c# string int type-conversion automapper


【解决方案1】:

我觉得你可以用ResolveUsing的方法来解决。

Mapper.CreateMap<Job, JobViewModel>()
    .ForMember(d => d.JobNumberFull,
    exp =>
    exp.ResolveUsing(j => string.Format("{0}-{1}-{2}", j.Prefix, j.JobNumber, j.Year)));

【讨论】:

  • 我接受了这个作为答案,因为它为我想要实现的目标提供了一种优雅的内联用法。我保留了我原来问题的更新,因为这显示了如何编写可重用的值转换器。
  • 感谢所有帮助我取得成果的人。
  • 我需要什么。清晰而简单。谢谢。
【解决方案2】:

您需要为从 Job 到 JobViewModel 的转换指定自定义转换函数。

Mapper.CreateMap<Job, JobViewModel>().ConvertUsing(
  job => new JobViewModel {
    JobNumberFull = string.Format("{0}-{1}-{2}",
                      job.Prefix, job.JobNumber, Job.Year)
  });

要将 Job 转换为 JobViewModel,请使用 Map 函数。

var jobViewModel = Mapper.Map<JobViewModel>(job);

要将作业列表转换为 JobViewModel,请使用 Select 扩展方法。

var jobViewModels = jobs.Select(job => Mapper.Map<JobViewModel>(job));

【讨论】:

  • Jeremy 感谢您的回复,这是因为我没有收到错误,但它没有填充字段,它们都是空的。我已经在我的 .ForMember 行中添加了我正在展平的其他几个字段,一旦投影完成,它们也为空。
  • 您是尝试从 Job 中创建 JobViewModel 还是从 JobViewModel 中创建 Job?
  • 哦,您问题中第二个代码块的第 2 行中的 ListJobsViewModel 类型是什么?
  • 我正在尝试从作业创建 JobViewModel。我从数据库中选择了许多工作,工作表有很多我需要显示的数据不需要的字段(我在上面缩短了我的工作类)所以我创建了一个 JobViewModel 来公开我需要显示的数据。
  • 我用我正在使用的完整测试代码更新了我的答案。它将 prefix-1-2013 输出到控制台。
猜你喜欢
  • 1970-01-01
  • 2011-10-02
  • 2011-03-06
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多