5

I am facing a challenge with AutoMapper between my source object and destination object. I will try to explain the sittuation. On my src object I have an string that according to its lenght it should be mapped to multiple properties of my destination object.

class source
{
   public int Id {get; set;}
   /* some other properties */
   public string Value {get; set;}
}

class destination
{
   public int Id {get; set;}
   /* some other properties with the same name as the source */
   public string Value1 {get; set;}
   public string Value2 {get; set;}
   public string Value3 {get; set;}
}

The max length expected is 30 chars (It can be less than that which will be mapped to only two properties or one). So every 10 will be mapped to each destination property. I was trying to use the ResolveUsing method from AutoMapper but there is no way to let the function to know which segment I should bring back. So I was thinking to ignore the mapping of this properties and do this manually after Automapper has dones its job with other properties

4

2 回答 2

10

您可以这样做的方法是.ConstructUsing告诉 AutoMapper 如何创建对象您可以创建一个手动映射Value1,的函数Value2Value3然后让 AutoMapper 映射剩余的属性。例如:

static destination ConstructDestination(source src)
{
    List<string> chunked = src.Value
        .Select((ch, index) => new { Character = ch, Index = index })
        .GroupBy(
            grp => grp.Index / 10,
            (key, grp) => new string(grp.Select(itm => itm.Character).ToArray()))
        .ToList();

    var dest = new destination
    {
        Value1 = chunked.Count > 0 ? chunked[0] : null,
        Value2 = chunked.Count > 1 ? chunked[1] : null,
        Value3 = chunked.Count > 2 ? chunked[2] : null
    };

    return dest;
}

Mapper.CreateMap<source, destination>()
    .ConstructUsing(ConstructDestination)
    .ForMember(dest => dest.Value1, opt => opt.Ignore())
    .ForMember(dest => dest.Value2, opt => opt.Ignore())
    .ForMember(dest => dest.Value3, opt => opt.Ignore());
    /* Id is mapped automatically. */

当然,如果在您的实际场景中您拥有三个以上的Value字段,这可能会变得很糟糕——在这种情况下,您可以使用反射来设置属性。

于 2014-11-13T20:09:38.467 回答
6

您可以使用 ForMember 规范创建映射函数

IE

private void CreateMap(){
    Mapper.CreateMap<source,destination>()
        .ForMember(v=> v.Value1,
            opts => opts.MapFrom( src=> src.Value.Substring(0,10)))
        .ForMember(v=> v.Value2,
            opts => opts.MapFrom( src=> src.Value.Substring(10,10)))
        .ForMember(v=> v.Value3,
            opts => opts.MapFrom( src=> src.Value.Substring(20,10)));
}

您可以只评估原始字符串包含适当长度的每个映射,否则返回 string.Empty 或填充它以满足您的需要。

用法(使用 LinqPad):

void Main(){
   CreateMap();
   var source = new source();
   source.Id=1;
   source.Value="123454678901234546789012345467";
   var res = Mapper.Map<destination>(source);
   res.Dump();
}
于 2014-11-13T20:12:11.577 回答