I am trying to map between two classes ParentA
and ParentB
using AutoMapper with a custom value converter. However, I am encountering an issue when mapping back from ParentB
to ParentA
.
We are using AutoMapper attributes to do the mapping.
Here is my code:
ParentA ssssssss = new ParentA { Id = 1, isActive = "Y", Name = "test" };
var response = automapper.Map<ParentB>(ssssssss);
response.Value = 500;
var yyyy = automapper.Map<ParentA>(response);
Class Definitions:
public class ParentA
{
public int Id { get; set; }
public string Name { get; set; }
public string isActive { get; set; }
}
[AutoMap(typeof(ParentA), ReverseMap = true)]
public class ParentB
{
public int Id { get; set; }
public string Name { get; set; }
[ValueConverter(typeof(IntConverter))]
[SourceMember("isActive")]
public int Value { get; set; }
}
Converter:
public class IntConverter : IValueConverter<string, int>
{
public int Convert(string sourceMember, ResolutionContext context)
{
if (sourceMember == "Y") return 100;
if (sourceMember == "N") return 200;
if (sourceMember == "P") return 500;
return 1000;
}
public string Convert(int sourceMember, ResolutionContext context)
{
throw new NotImplementedException();
}
}
The mapping from ParentA
to ParentB
works correctly.
When mapping back from ParentB
to ParentA
, it fails because the Convert
method for the reverse mapping in IntConverter
is not implemented.
Could you help me to implement the reverse mapping in IValueConverter
?
After some trials and errors, I think that attribute-based mapping has some limitations when performing the reverse mapping with the value converter.
The implementation of Value Converter supports only one-way mapping.
Thus, would recommend removing the ReverseMap = true
from the [AutoMap]
attribute. And you should apply the [AutoMap]
attribute to the ParentB
class and [SourceMember]
and [ValueConverter]
attributes to the isActive
property.
[AutoMap(typeof(ParentB))]
public class ParentA
{
public int Id { get; set; }
public string Name { get; set; }
[ValueConverter(typeof(StringConverter))]
[SourceMember("Value")]
public string isActive { get; set; }
}
[AutoMap(typeof(ParentA))]
public class ParentB
{
public int Id { get; set; }
public string Name { get; set; }
[ValueConverter(typeof(IntConverter))]
[SourceMember("isActive")]
public int Value { get; set; }
}
public class StringConverter : IValueConverter<int, string>
{
public string Convert(int sourceMember, ResolutionContext context)
{
if (sourceMember == 100)
return "Y";
if (sourceMember == 200)
return "N";
if (sourceMember == 500)
return "P";
return null;
}
}
Otherwise, you should work with Fluent configuration (Profile
and/or MappingConfiguration
) to provide the mapping rule for the reverse mapping for the Value
/isActive
property.
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<ParentA, ParentB>()
.ForMember(dest => dest.Value, opt => opt.ConvertUsing(new IntConverter(), src => src.isActive))
.ReverseMap()
.ForMember(dest => dest.isActive, opt => opt.ConvertUsing(new StringConverter(), src => src.Value));
}
}