AutoMapper mapping to a property of a nullable property

主宰稳场 提交于 2021-02-07 11:45:29

问题


How can you map a property to a sub-property that may be null?

eg the following code will fail with a NullReferenceException because the Contact's User property is null.

using AutoMapper;

namespace AutoMapperTests
{
    class Program
    {
        static void Main( string[] args )
        {
            Mapper.CreateMap<Contact, ContactModel>()
                .ForMember( x => x.UserName,  opt => opt.MapFrom( y => y.User.UserName ) );

            Mapper.AssertConfigurationIsValid();

            var c = new Contact();

            var co = new ContactModel();

            Mapper.Map( c, co );
        }
    }

    public class User
    {
        public string UserName { get; set; }
    }

    public class Contact
    {
        public User User { get; set; }
    }

    public class ContactModel
    {
        public string UserName { get; set; }
    }
}

I'd like ContactModel's UserName to default to an empty string instead.

I have tried the NullSubstitute method, but I assume that's trying to operate with User.Username, rather than just on the User property.


回答1:


You could write the mapping code like follows:

Mapper.CreateMap<Contact, ContactModel>()
            .ForMember( x => x.UserName,  opt => opt.MapFrom( y => (y.User != null) ? y.User.UserName : "" ) );

This will check if the User is null or not and then assign either an emtpy string or the UserName.




回答2:


If you find yourself doing a lot of null checking like in Dave's answer, you might consider applying the technique I've blogged about a while ago: Getting rid of null checks in property chains. This will allow you to write this:

Mapper.CreateMap<Contact, ContactModel>()
    .ForMember(x => x.UserName,
        opt => opt.NullSafeMapFrom(y => y.User.UserName) ?? string.Empty);



回答3:


A solution I've used is to create a closure around the original delegate, which wraps it in a try/catch block. It's unfortunately necessary to use Expression.Compile() to stop Visual Studio from catching the exception when it's thrown in the original delegate. Probably not recommended in high performance environments, but I've never had any issue using it in regular UI stuff. Your milage may vary.

Extension method

public static class AutoMapperExtensions
{
    public static void NullSafeMapFrom<T, TResult>(this IMemberConfigurationExpression<T> opt, Expression<Func<T, TResult>> sourceMemberExpression)
    {
        var sourceMember = sourceMemberExpression.Compile();

        opt.MapFrom(src =>
        {
            try
            {
                return sourceMember(src);
            }
            catch (NullReferenceException)
            {}

            return default(TResult);
        });
    }
}

Usage

.ForMember(dest => dest.Target, opt => opt.NullSafeMapFrom(src => src.Something.That.Will.Throw));


来源:https://stackoverflow.com/questions/4092907/automapper-mapping-to-a-property-of-a-nullable-property

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!