AutoMapper TwoWay Mapping with same Property Name

蹲街弑〆低调 提交于 2019-12-05 16:48:08

Is this the most optimal way to do the mapping, or is AutoMapper capable of mapping Roles to Roles on its own?

If the property names are identical, you should not have to manually provide a mapping:

Mapper.CreateMap<UserModel, UserViewModel>();
Mapper.CreateMap<UserViewModel, UserModel>();

Just make sure the inner types are mapped as well (RoleViewModelRoleModel)

What this means, however, is that if you change a source or destination property name, AutoMapper mappings can fail silently and cause hard to track down problems (e.g., if you changed UserModel.Roles to UserModel.RolesCollection without changing UserViewModels.Roles).

AutoMapper provides a Mapper.AssertConfigurationIsValid() method that will check all of your mappings for errors and catch misconfigured mappings. It's useful to have a unit test that runs with the build that validates your mappings for this kind of problem.

You don't need to map the properties. Just make sure that the property names match and there is a mapping defined between them.

Mapper.CreateMap<UserModel, UserViewModel>();
Mapper.CreateMap<UserViewModel, UserModel>();
Mapper.CreateMap<RoleModel, RoleViewModel>();
Mapper.CreateMap<RoleViewModel, RoleModel>();

Or with the cooler way I just found out:

Mapper.CreateMap<UserModel, UserViewModel>().ReverseMap();
Mapper.CreateMap<RoleModel, RoleViewModel>().ReverseMap();

All the other answers, are much better (which I gave an upvote to each).

But what I wanted to post here is a quick playground that you could copy and past right into LinqPad in C# program mode and play your idea's without messing with your actual code.

Another awesome thing about moving all your conversions into a TyperConverter class is that your conversions are now Unit Testable. :)

Here you will notice that the model and viewmodel are almost identical except for one property. But through this process the right property is converted to the correct property in the destination object.

Copy this code into LinqPad and you can run it with the play button after switching to C# Program mode.

void Main()
{
    AutoMapper.Mapper.CreateMap<UserModel, UserViewModel>().ConvertUsing(new UserModelToUserViewModelConverter());
    AutoMapper.Mapper.AssertConfigurationIsValid();

    var userModel = new UserModel
    {
        DifferentPropertyName = "Batman",
        Name = "RockStar",
        Roles = new[] {new RoleModel(), new RoleModel() }
    };

    var userViewModel = AutoMapper.Mapper.Map<UserViewModel>(userModel);
    Console.WriteLine(userViewModel.ToString());
}

// Define other methods and classes here
public class UserModel
{
    public string Name {get;set;}
    public IEnumerable<RoleModel> Roles { get; set; }
    public string DifferentPropertyName { get; set; }
}

public class UserViewModel 
{
    public string Name {get;set;}
    public IEnumerable<RoleModel> Roles { get; set; } // notice the ViewModel
    public string Thingy { get; set; }

    public override string ToString()
    {
        var sb = new StringBuilder();
        sb.AppendLine(string.Format("Name: {0}", Name));
        sb.AppendLine(string.Format("Thingy: {0}", Thingy));
        sb.AppendLine(string.Format("Contains #{0} of roles", Roles.Count()));

        return sb.ToString();
    }
}

public class UserModelToUserViewModelConverter : TypeConverter<UserModel, UserViewModel>
{
    protected override UserViewModel ConvertCore(UserModel source)
    {
        if(source == null)
        {
            return null;
        }

        //You can add logic here to deal with nulls, empty strings, empty objects etc
        var userViewModel = new UserViewModel
        {
             Name = source.Name,
             Roles = source.Roles, 
             Thingy = source.DifferentPropertyName
        };
        return userViewModel;
    }
}

public class RoleModel
{
    //no content for ease, plus this has it's own mapper in real life
}

Result from the Console.WriteLine(userViewModel.ToString());:

Name: RockStar
Thingy: Batman
Contains #2 of roles

Inside the Startup.cs in the Configure() method:

Mapper.Initialize(config => {
                    config.CreateMap<UserModel, UserViewModel>().ReverseMap();
                    // other maps you want to do.
                });
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!