简体   繁体   中英

Automapper - Mapping a property to a method

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");

Use following code, hope It will be helpful.

CreateMap<UserDTO, User>()
  .ForMember(desti => desti.Age, source => source.MapFrom(m => m.Age))
  .ForMember(desti => desti.Name, source=> source.MapFrom(m => m.Name))
  .ForMember(desti => desti.Active, source=> source.MapFrom(m => m.Active));

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));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM