mappingvalueinjecter

Flatten Domain Class To ViewModel When Source Is Complex


I am using ValueInjecter to map domain classes to my view models. My domain classes are complex. To borrow an example from this question:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }
}

public class Address
{
   public int Id { get; set; }
   public string City { get; set; }
   public string State { get; set; }
   public string Zip { get; set; }
}

//  VIEW MODEL 

public class PersonViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int PersonId { get; set; }
    public int AddressId { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; } 
}

I have looked at FlatLoopInjection, but it expects the view model classes to be prefixed with nested domain model type like so:

public class PersonViewModel
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public int Id { get; set; }
   public int AddressId { get; set; }
   public string AddressCity { get; set; }
   public string AddressState { get; set; }
   public string AddressZip { get; set; } 

}

The OP in the linked question altered his view models to match the convention expected by FlatLoopInjection. I don't want to do that. How can I map my domain model to the original unprefixed view model? I suspect that I need to override FlatLoopInjection to remove the prefix, but I am not sure where to do this. I have looked at the source for FlatLoopInjection but I am unsure if I need to alter the Match method or the SetValue method.


Solution

  • you don't need flattening, add the map first:

    Mapper.AddMap<Person, PersonViewModel>(src =>
    {
        var res = new PersonViewModel();
        res.InjectFrom(src); // maps properties with same name and type
        res.InjectFrom(src.Address);
        return res;
    });
    

    and after that you can call:

    var vm = Mapper.Map<PersonViewModel>(person);