jeudi 30 mars 2017

Mapping DTO to DTO pattern

I'm going to map a big DTO coming from a rest service to another different big DTO.
The two DTOs are different but semantically they are the same.
I'm looking for a pattern and i would like to implement the mapper using a TDD approach.
Ideally i want one or more test for one field-to-field mapping operation.

The problem

public class DestinationDTO {
    public int Id {get;set;}
    public string FieldA {get;set;}
    public SubObjectDTO SubObjectDTO {get;set;}
    public AnotherObjectDTO AnotherObjectDTO {get;set;}
    public ICollection<string> MyArray {get;set;}

} 

public class SourceDTO {
    public int Id {get;set;}
    public SourceObjectDTO {get;set;}
    public AnotherSourceObject {get;set;}
}

// perform the mapper invocation given the sourceDTO
public class MapperConsumer {
    public DestinationDTO MapIntoDestination(SourceDTO sourceDTO){
        var myMapper = new Mapper();
        DestinationDTO mapped = myMapper(sourceDTO);
        return mapped;
    }
}

My solution

The only approach I can figure out is to have and after inject an Interface that is responsible for handle the mapping of only one field, but this will increase the complexity of my project and the complexity of the root mapper (because i will need to inject 100 interfaces).

public class Mapper {
     private readonly IFieldAMapper _fieldAMapper;
     private readonly ISubObjectMapper _subObjectMapper;
     /*
     // ... other injected mappers
     */

     public Mapper(IFieldAMapper fieldAMapper, 
                   ISubObjectMapper subObjectMapper, 
                  /*
                  // ... injected other mappers
                  */)
     } 

     public DestinationDTO map(SourceDTO sourceDTO) {
            DestinationDTO dest = new DestionationDTO();
            dest.FieldA = _fieldAMapper.map(sourceDTO);
            dest.SubObjectDTO = _subObjectMapper.map(sourceDTO);
            /*
            // ... invoke the mappers for all fields
            */

            //finally return the builded DTO
            return destDTO;
     }



}

public class FieldAMapper : IFieldAMapper {
    public string map(SourceDTO sourceDTO){
        if(sourceDTO.SubObjectDTO != null){
            return sourceDTO.SubObjectDTO.SourceProperty;
        }
        return "DefaultValueForFieldA";
    }
}

My reviewed solution

Now i come back with my initial idea and i'm creating an IMapper only for handle the SubObjects mapping and mapping the primitive fields inside the map method.

The question

How do you handle this kind of problems ? Do you know a best practices or a pattern for this kind of problem ?

Aucun commentaire:

Enregistrer un commentaire