title: DTO to Entity Mapping Tool
body: <p>I have an entity class <code>Person</code> and its corresponding DTO class <code>PersonDto</code>.</p>
  
  <pre><code>public class Person: Entity
  {
    public virtual string Name { get; set; }
    public virtual string Phone { get; set; }
    public virtual string Email { get; set; }
    public virtual Sex Sex { get; set; }
    public virtual Position Position { get; set; }
    public virtual Division Division { get; set; }
    public virtual Organization Organization { get; set; }
  }
  
  public class PersonDto: Dto
  {
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public Guid SexId { get; set; }
    public Guid PositionId { get; set; }
    public Guid DivisionId { get; set; }
    public Guid OrganizationId { get; set; }
  }
  </code></pre>
  
  <p>After receiving a DTO object I have to convert it into a person entity. Now I do it completely manually. The code looks like this.</p>
  
  <pre><code>public class PersonEntityMapper: IEntityMapper&lt;Person, PersonDto&gt;
  {
    private IRepository&lt;Person&gt; _personRepository;
    private IRepository&lt;Sex&gt; _sexRepository;
    private IRepository&lt;Position&gt; _positionRepository;
    private IRepository&lt;Division&gt; _divisionRepository;
    private IRepository&lt;Organization&gt; _organizationRepository;
  
    public PersonEntityMapper(IRepository&lt;Person&gt; personRepository,
                              IRepository&lt;Sex&gt; sexRepository,
                              IRepository&lt;Position&gt; positionRepository,
                              IRepository&lt;Division&gt; divisionRepository,
                              IRepository&lt;Organization&gt; organizationRepository)
    {
      ... // Assigning repositories
    }
  
    Person Map(PersonDto dto)
    {
      Person person = CreateOrLoadPerson(dto);
  
      person.Name = dto.Name;
      person.Phone = dto.Phone;
      person.Email = dto.Email;
  
      person.Sex = _sexRepository.LoadById(dto.SexId);
      person.Position = _positionRepository.LoadById(dto.PositionId);
      person.Division = _divisionRepository.LoadById(dto.DivisionId);
      person.Organization = _organizationRepository.LoadById(dto.OrganizationId);
  
      return person;
    }
  }
  </code></pre>
  
  <p>The code is in fact trivial. But as the number of entities grows so does the number of mapper classes. The result is lots of similar code. Another issue is that when there are mode associations I have to add constructor parameteres for additional repositories. I tried to inject a some kind of a repository factory instead, but it smelled a bad-known <code>Service Locator</code> so I reverted to an original solution.  </p>
  
  <p>Unit testing of these mappers also results in a number of similar-looking test methods.</p>
  
  <p>With all this been said I wonder if there exists a solution that can reduce the amount of manually written code and make the unit testing easier.  </p>
  
  <p>Thanks in advance.  </p>
  
  <h2>UPDATE</h2>
  
  <p>I'd accomplished the task with <code>Value Injecter</code> but then I realized that I could safely remove it and the rest would still work. Here is the resulting solution.</p>
  
  <pre><code>public abstract class BaseEntityMapper&lt;TEntity, TDto&gt; : IEntityMapper&lt;TEntity, TDto&gt;
          where TEntity : Entity, new()
          where TDto : BaseDto
      {
          private readonly IRepositoryFactory _repositoryFactory;
  
          protected BaseEntityMapper(IRepositoryFactory repositoryFactory)
          {
              _repositoryFactory = repositoryFactory;
          }
  
          public TEntity Map(TDto dto)
          {
              TEntity entity = CreateOrLoadEntity(dto.State, dto.Id);
  
              MapPrimitiveProperties(entity, dto);
              MapNonPrimitiveProperties(entity, dto);
  
              return entity;
          }
  
          protected abstract void MapNonPrimitiveProperties(TEntity entity, TDto dto);
  
          protected void MapPrimitiveProperties&lt;TTarget, TSource&gt;(TTarget target, TSource source, string prefix = "")
          {
              var targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p =&gt; p.Name);
              var sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p =&gt; p.Name);
  
              foreach (var targetProperty in targetProperties) {
                  foreach (var sourceProperty in sourceProperties) {
                      if (sourceProperty.Name != string.Format("{0}{1}", prefix, targetProperty.Name)) continue;
                      targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
                      break;
                  }
              }
          }
  
          protected void MapAssociation&lt;TTarget, T&gt;(TTarget target, Expression&lt;Func&lt;T&gt;&gt; expression, Guid id) where T : Entity
          {
              var repository = _repositoryFactory.Create&lt;T&gt;();
              var propertyInfo = (PropertyInfo)((MemberExpression)expression.Body).Member;
              propertyInfo.SetValue(target, repository.LoadById(id), null);
          }
  
          private TEntity CreateOrLoadEntity(DtoState dtoState, Guid entityId)
          {
              if (dtoState == DtoState.Created) return new TEntity();
  
              if (dtoState == DtoState.Updated) {
                        return _repositoryFactory.Create&lt;TEntity&gt;().LoadById(entityId);
              }
              throw new BusinessException("Unknown DTO state");
          }
      }  
  </code></pre>
  
  <p>Mapping of each entity is performed with a concrete class derived from <code>BaseEntityMapper</code>. The one for <code>Person</code> entities looks like this.  </p>
  
  <pre><code>public class PersonEntityMapper: BaseEntityMapper&lt;Person, PersonDto&gt;
      {
          public PersonEntityMapper(IRepositoryFactory repositoryFactory) : base(repositoryFactory) {}
  
          protected override void MapNonPrimitiveProperties(Person entity, PersonDto dto)
          {
              MapAssociation(entity, () =&gt; entity.Sex, dto.SexId);
              MapAssociation(entity, () =&gt; entity.Position, dto.PositionId);
              MapAssociation(entity, () =&gt; entity.Organization, dto.OrganizationId);
              MapAssociation(entity, () =&gt; entity.Division, dto.DivisionId);
          }
      }
  </code></pre>
  
  <p>Explicitly calling <code>MapAssociation</code> protects against future properties renamings.</p>