need help with IValueConverter

23 views
Skip to first unread message

Marco Antonio Garcia Reboiro

unread,
Apr 28, 2021, 1:40:23 AMApr 28
to AutoMapper-users
Hi all, I'm sort of lost with how to implement a mapping. I'll try to describe the situation. I'm mapping from ParcelRequestDTO to NParcel. Here are both classes:

    public class ParcelRequestDTO
    {
        public decimal Length { get; set; }
        public decimal Width { get; set; }
        public decimal Height { get; set; }
        public string DistanceUnit { get; set; }
        public decimal Weight { get; set; }
        public string MassUnit { get; set; }
        public string Metadata { get; set; }
    }

    public partial class NParcel
    {
        public int Id { get; set; }
        public decimal? Length { get; set; }
        public decimal? Width { get; set; }
        public decimal? Height { get; set; }
        public int? DistanceUnitId { get; set; }
        public decimal Weight { get; set; }
        public int? MassUnitId { get; set; }
    }

NParcel is actually part of the an EF entity. DistanceUnitId  and MassUnitId  are foreign keys, so their values can be null or must be a reference to a primary key.

So, in my DTO I receive MassUnit as a string, such as "lb", "oz", "gr", "K", etc. I need to find the corresponding id for any of those labels in the proper table. So I'm trying to implement a value converter:

    public class ResolveMassUnits : IValueConverter<string, int>
    {
        private readonly IMassUnitsService _massUnitsService;
        public ResolveMassUnits(IMassUnitsService massUnitsService)
        {
            _massUnitsService = massUnitsService;
        }

        public int Convert(string sourceMember, ResolutionContext context)
        {
            int? retVal = _massUnitsService.GetIdByName(sourceMember);
            if (retVal == null)
            {
                retVal = _massUnitsService.GetIdByName("lb");
            }
            return (int)retVal;
        }
    }

as you see I'm trying to injection (.NET Core 3 dependency injection model) to instantiate the ResolveMassUnits class (I'm not sure I'm doing this correctly, so if you see an issue here, please advice).

My initial problem is, however, that when I try to set the mapping, I get a compile error. This is what I'm doing:

    public class RequestsProfile : Profile
    {
        public RequestsProfile()
        {

           CreateMap<ParcelRequestDTO, NParcel>()
                .ForMember(dest => dest.ParcelState, opt => opt.Ignore())
                .ForMember(dest => dest.DistanceUnit, opt => opt.Ignore())
                .ForMember(dest => dest.MassUnitId, opt => opt.ConvertUsing<ResolveMassUnits, string>(src => src.MassUnit))
                .ForMember(dest => dest.ParcelTemplate, opt => opt.Ignore())
                ;
       }  
    }

When I compile, I get these errors:

Severity Code Description Project File Line Suppression State
Error CS0311 The type 'BetterTrucks.API.Mappings.ResolveMassUnits' cannot be used as type parameter 'TValueConverter' in the generic type or method 'IMemberConfigurationExpression<ParcelRequestDTO, NParcel, object>.ConvertUsing<TValueConverter, TSourceMember>(Expression<Func<ParcelRequestDTO, TSourceMember>>)'. There is no implicit reference conversion from 'BetterTrucks.API.Mappings.ResolveMassUnits' to 'AutoMapper.IValueConverter<string, object>'. BetterTrucks.API C:\Projects\BestTrucks\Repo\src\IO.Swagger\Mappings\RequestsProfile.cs 146 Active
Error CS0246 The type or namespace name 'ResolveMassUnits' could not be found (are you missing a using directive or an assembly reference?) CoreAPIServiceTesting C:\Projects\BestTrucks\Repo\src\IO.Swagger\Mappings\RequestsProfile.cs 146 Active

So obviously it's not finding ResolveMassUnits.

Anyone has any idea of what I'm doing wrong? I'm have tried to go around this in several different ways, but for the sake of it, I cannot find a way do handle this mapping properly.

Thanks in advance.






KC REDUS

unread,
Apr 30, 2021, 10:20:41 AMApr 30
to AutoMapper-users
I think the issue is that your dest.MassUnitId is nullable but you setup the IValueConverter as <string,int>.  If I change the signature to <string,int?> and update the return type etc., it compiles.


public class ResolveMassUnits : IValueConverter<string, int?>

{
    private readonly IMassUnitsService _massUnitsService;   

    public ResolveMassUnits(IMassUnitsService massUnitsService)
    {
        _massUnitsService = massUnitsService;
    }

    public int? Convert(string sourceMember, ResolutionContext context)

    {
        int? retVal = _massUnitsService.GetIdByName(sourceMember);
        if (retVal == null)
        {
            retVal = _massUnitsService.GetIdByName("lb");
        }
        return retVal;
Reply all
Reply to author
Forward
0 new messages