Aria
Aria

Reputation: 3844

Automapper doesn't work between class and struct AfterMap

Suppose this Enum contract :

  [DataContract]
public enum ReportType_DTO
{
    [EnumMember]
    Voice,
    [EnumMember]
    Text,
    [EnumMember]
    File
}

which have three members from 0 to 2 in the other side I have another Enum which have 7 member as:

 public enum RptType
{
    Word = 0,
    Dynamic = 1,
    Basic = 2,
    StructuredReport = 3,
    Word2007 = 4,
    PDF = 5,
    WebReport = 6,
    WebTemplate = 7
}

so I configure mapping as:

  var mapper1 = new MapperConfiguration((cfg) =>
            cfg.CreateMap<Report_C, Report_DTO>().AfterMap((reportC, reportDTO) =>
            { 
                switch ((RptType)reportC.Type)
                {
                    case RptType.Dynamic:
                    case RptType.PDF:
                    case RptType.Word:
                    case RptType.Word2007:
                    case RptType.WebTemplate:
                        reportDTO.Type = ReportType_DTO.File;
                        break;
                    case RptType.StructuredReport:
                        reportDTO.Type = ReportType_DTO.Voice;
                        break;
                    case RptType.Basic:
                    case RptType.WebReport:
                        reportDTO.Type = ReportType_DTO.Text;
                        break;
                }
                reportDTO.ReportUID = reportC.SOPInstanceUID;
            }))
            .CreateMapper();

and map the collection one by one:

  var foundReports = pacsReports.Collection.Select(r => mapper1.Map<Report_DTO>(r)).ToList();

case RptType.StructuredReport happened for one of collections member but when I checked the collection it seem that prop doesn't get new value as picture below: enter image description here

this is clear in client-side we ending up with exception like :

Enum value '3' is invalid for type 'xxx.ReportType_DTO' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.

is there another ways to force Automapper change the value explicitly?

UPDATE1:

Report_DTO is a struct type but Report_C is a class, can it be the reason (something like call by reference or call by value for struct in mapping) ?

UPDATE2:

Yes struct is the reason, by changing struct to class it work well, but I am returning DTO_OUT as struct for some reason to force operation don't return null so I can't change them to class, I believe there must be a solution to tell autommaper call by reference, I think AfterMape is a void method which change entered param in call by reference mechanism.

any idea and help would be appreciated.

Upvotes: 2

Views: 604

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205589

There is no way to let AutoMapper pass struct by reference to AfterMap action. So you need a different approach, not based on AfterMap.

One way is to create mapping from RptType to ReportType_DTO wrapping the switch logic in ConvertUsing. Then create a mapping from Report_C to Report_DTO with typical ForMember setup:

var mapper1 = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<RptType, ReportType_DTO>().ConvertUsing(rptType =>
    {
        switch (rptType)
        {
            case RptType.StructuredReport:
                return ReportType_DTO.Voice;
            case RptType.Basic:
            case RptType.WebReport:
                return ReportType_DTO.Text;
            default:
                return ReportType_DTO.File;
        }
    });

    cfg.CreateMap<Report_C, Report_DTO>()
        .ForMember(reportDTO => reportDTO.Type, opt => opt.MapFrom(reportC => (RptType)reportC.Type))
        .ForMember(reportDTO => reportDTO.ReportUID, opt => opt.MapFrom(reportC => reportC.SOPInstanceUID));
})
.CreateMapper();

Upvotes: 3

Related Questions