代码之家  ›  专栏  ›  技术社区  ›  David Gardiner

自动映射到可为空属性的属性

  •  10
  • David Gardiner  · 技术社区  · 15 年前

    例如,由于联系人的用户属性为空,下面的代码将因NullReferenceException而失败。

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

    我希望ContactModel的用户名默认为空字符串。

    3 回复  |  直到 15 年前
        1
  •  20
  •   davehauser    15 年前

    您可以编写如下映射代码:

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

    这将检查 User UserName .

        2
  •  6
  •   Sandor Drieënhuizen    8 年前

    如果你发现自己像戴夫的答案那样做了很多空检查,你可以考虑应用一下我不久前在博客中提到的技术: Getting rid of null checks in property chains

    Mapper.CreateMap<Contact, ContactModel>()
        .ForMember(x => x.UserName,
            opt => opt.NullSafeMapFrom(y => y.User.UserName) ?? string.Empty);
    
        3
  •  3
  •   James Gregory    15 年前

    我使用的一个解决方案是围绕原始委托创建一个闭包,该闭包将其包装在try/catch块中。不幸的是必须使用 Expression.Compile() 阻止Visual Studio在原始委托中引发异常时捕获该异常。在高性能环境中可能不推荐使用它,但在常规UI中使用它从来没有遇到过任何问题。你的相似之处可能不同。

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

    用法

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