I am currently working with classes that are defined as such:
public class User
{
public string Name { get; private set; }
public int Age { get; private set; }
public bool Active { get; private set; }
public void Name(string name)
{
Name = name;
}
public void Age(int age)
{
Age = age;
}
public void Active(bool active)
{
Active = active;
}
}
public class UserDTO
{
public string Name { get; set; }
public int Age { get; set; }
public bool Active { get; set; }
}
I have configured my mapper
as such:
MapperConfiguration config = new(cfg =>
{
cfg.CreateMap<User, UserDTO>();
cfg.CreateMap<UserDTO, User>();
});
I have no control over the class User
and will not be able to make any modifications to it.
var user = UserController.GetUser();
var userDTO = Mapper.Map<UserDTO>(user);
The above is how I usually do it from one direction, but now I want to be able to map
UserDTO
back to User
and because setting of values are done through methods instead, I am not sure how to go about it.
What I would like to be able to do is:
userDTO.Name = "John Doe";
Mapper.Map(userDTO, user);
and behind the scene, it would actually do a
user.Name("John Doe");
Because you have a special behaviour on creating a Destination
instance out of a Source
instance, you have to use the .ConvertUsing()
method and manually create and fill your new (or existing) instance.
An example would be:
public class Source
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Destination
{
private string _name;
private string _id;
public string Name { get => _name; }
public string Id { get => _id; }
public void UpdateName(string name)
{
_name = name;
}
public void UpdateId(string id)
{
_id = id;
}
}
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Destination>()
.ConvertUsing((source, existing, context) =>
{
// If existing is not null, the user called .Map() with an existing
// destination instance, which should be filled.
var dest = existing ?? new Destination();
// Call special method to fill dest instance.
dest.UpdateName(source.Name);
// if mapper is needed for other (nested) mappings, it can be used
var id = context.Mapper.Map<string>(source.Id);
dest.UpdateId(id);
return dest;
});
}
}
public class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(c => c.AddProfile<MappingProfile>());
var mapper = config.CreateMapper();
var source = new Source
{
Id = Guid.NewGuid(),
Name = "Some name",
};
var dest = mapper.Map<Destination>(source);
Console.WriteLine(JsonSerializer.Serialize(dest));
}
}