如何将属性映射到可能为null的子属性?
例如,以下代码将因NullReferenceException而失败,因为Contact的User属性为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; }
}
}
Run Code Online (Sandbox Code Playgroud)
我想将ContactModel的UserName默认为空字符串.
我已经尝试过NullSubstitute方法,但我认为它试图使用User.Username,而不是仅仅在User属性上.
dav*_*ser 20
您可以编写如下映射代码:
Mapper.CreateMap<Contact, ContactModel>()
.ForMember( x => x.UserName, opt => opt.MapFrom( y => (y.User != null) ? y.User.UserName : "" ) );
Run Code Online (Sandbox Code Playgroud)
这将检查是否User为null,然后分配一个emtpy字符串或UserName.
如果您发现自己在Dave的答案中进行了大量的空检查,那么您可能会考虑应用我之前写过的博客技术:摆脱属性链中的空检查.这将允许你写这个:
Mapper.CreateMap<Contact, ContactModel>()
.ForMember(x => x.UserName,
opt => opt.NullSafeMapFrom(y => y.User.UserName) ?? string.Empty);
Run Code Online (Sandbox Code Playgroud)
我使用的解决方案是围绕原始委托创建一个闭包,将其包装在 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);
});
}
}
Run Code Online (Sandbox Code Playgroud)
.ForMember(dest => dest.Target, opt => opt.NullSafeMapFrom(src => src.Something.That.Will.Throw));
Run Code Online (Sandbox Code Playgroud)