如果我想使用UseDestinationValue
方法中的行为,但仅当目标属性不是null
时,如何配置AutoMapper映射。
类似的东西:
Mapper.CreateMap<Item, ItemViewModel>()
.ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true))
修改
class ItemDetails {
public string Info { get; set; }
public string ImportantData { get; set; } // only in Domain, not in ViewModel
}
class Item {
public ItemDetails Details { get; set; }
}
class ItemDetailsViewModel {
public string Info { get; set; }
}
class ItemViewModel {
public ItemDetailsViewModel Details { get; set; }
}
现在使用的例子。我有一个ItemViewModel
类,我想将它映射到Item
类。
映射配置:
Mapper.CreateMap<Item, ItemViewModel>()
.ForMember(x => x.Details, _ => _.UseDestinationValue())
第一种情况 - 目标属性Item.Details
属性为NOT NULL。现在我希望AutoMapper 使用此Details
属性的目标实例,因为它不是null。
逻辑看起来像这样:
var item = new Item {
Details = new Details {
Info = "Old text",
ImportantData = "Data"
}
};
var itemViewModel = new ItemViewModel {
Details = new DetailsViewModel {
Info = "New text"
}
};
Mapper.Map(itemViewModel, item);
由于存在UseDestinationValue
,AutoMapper将离开item.Details
实例并仅设置item.Details.Info
属性。
第二种情况 - 目标属性Item.Details
属性为NULL。现在我想让AutoMapper 不使用这个空实例,但要创建一个新实例。问题是如何配置映射以考虑这种情况?
逻辑如下:
var item = new Item {
Details = null
};
var itemViewModel = new ItemViewModel {
Details = new DetailsViewModel {
Info = "New text"
}
};
Mapper.Map(itemViewModel, item);
问题
这里我遇到了一个问题,因为在映射之后,item.Details
属性将为null(因为在这种情况下使用UseDestinationValue
null
)。
原因
NHibernate从数据库中获取实体后,将其放入代理中。所以加载对象的Details
属性不是类型:ItemDetails
,而是ItemDetailsNHibernateProxy
- 所以当我想将这个现有对象保存到数据库时,我必须使用这种类型后来。但是如果此属性为null
,则我无法使用空目标值,因此Automapper应创建一个新实例。
谢谢, 克里斯
答案 0 :(得分:1)
有同样的问题,但有EF。 Cryss'关于使用BeforeMap的评论指出了我正确的方向。
我最终得到的代码类似于:
在Configure()方法中:
Mapper.CreateMap<ItemViewModel, Item>()
.AfterMap((s, d) => { MapDetailsAction(s, d); })
.ForMember(dest => dest.Details, opt => opt.UseDestinationValue());
然后是行动:
Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
{
if (destination.Details == null)
{
destination.Details = new Details();
destination.Details =
Mapper.Map<ItemViewModel, Item>(
source.Details, destination.Details);
}
};
答案 1 :(得分:0)
我认为NullSubstitute
选项适合您。请参阅:http://weblogs.asp.net/psteele/archive/2011/03/18/automapper-handling-null-members.aspx
修改强>
看起来您可能需要在详细信息的映射中添加一些条件逻辑(并跳过UseDestinationValue
选项):
.ForMember(d => d.Details,
o => o.MapFrom(s => s.Details == null ? new ItemDetails() : Mapper.Map<ItemDetailsViewModel, ItemDetails>(s.Details))
答案 2 :(得分:0)
我遇到了与NHibernate实体相同的问题,我找到了非常简单的解决方案。
您应该在ItemViewModel构造函数中初始化Details属性。这样,目标值永远不为null。当然,这不适用于更复杂的情况(如抽象类)。