简体   繁体   中英

How to map two different datatype fields using Automapper?

I am trying to map fields of an object with child collection of source using Automapper through ProjectTo IQueryable as following:

var map2 = cfg.CreateMap<SourceModel, DestinationModel>(); 

map2.ForMember(fieldName, opt => opt.MapFrom(source => source.CustomFieldValues.FirstOrDefault(f => f.Name == fieldName).Value));

Models are as following:

public class SourceModel
{
  public IEnumerable<CustomFieldValue> CustomFieldValues { get; set; }
}

public class CustomFieldValue
{

    public string Name { get; set; }
    public string Value { get; set; }
}

public class DestinationModel
{
    public string _CUSTOM_Test { get; set; }
    public int _CUSTOM_Mynumber { get; set; }
    public DateTime _CUSTOM_mydate { get; set; }
    public bool _CUSTOM_mybool { get; set; }
    public decimal _CUSTOM_numberdec { get; set; }
    public int _CUSTOM_numint { get; set; }
    public int _CUSTOM_numper { get; set; }
    public DateTime _CUSTOM_mydate2 { get; set; }
    public DateTime _CUSTOM_mydate3 { get; set; }
    public DateTime _CUSTOM_mydate4 { get; set; }
    public int _CUSTOM_mynum2 { get; set; }
}

Expected Result: As the collection contains only string values but I need to map with different datatypes based on field name.

Actual Result: But when I try to apply conversion then queryable throws exception because sql query doesn't support this conversion.

You can use AutoMapper's Custom Type Converters .

AutoMapper does not know about any mapping from string to int for example so to create maps for these types, we must supply a custom type converter. This can be achieved by using ConvertUsing() method.

Mapper.Initialize(configuration =>
{
    configuration.CreateMap<string, int>().ConvertUsing(s => Convert.ToInt32(s));
    configuration.CreateMap<string, DateTime>().ConvertUsing(s => new DateTimeTypeConverter().Convert(s));
    configuration.CreateMap<string, bool>().ConvertUsing(s => Convert.ToBoolean(s));
    configuration.CreateMap<string, decimal>().ConvertUsing(s => Convert.ToDecimal(s));
    configuration.CreateMap<SourceModel, DestinationModel>()
        .ForMember("_CUSTOM_Mynumber", opt => opt.MapFrom(src => src.CustomFieldValues.FirstOrDefault(x => x.Name == "_CUSTOM_Mynumber").Value));
});

The example above shows how we can convert int , bool , and decimal . For DateTime , we'll use ITypeConverter .

public interface ITypeConverter<in TSource, TDestination>
{
    TDestination Convert(TSource source);
}

Then define a custom convertion:

public class DateTimeTypeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(source)
    {
        return Convert.ToDateTime(source);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM