C# 仅当目标属性不为null时使用DestinationValue
当我想使用C# 仅当目标属性不为null时使用DestinationValue,c#,.net,automapper,C#,.net,Automapper,当我想使用UseDestinationValue方法中的行为,但仅当目标属性不是null时,如何配置自动映射 诸如此类: Mapper.CreateMap<Item, ItemViewModel>() .ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true)) 现在是用法示例。我有一个ItemViewModel类,我想将它映射到Item类 映射配
UseDestinationValue
方法中的行为,但仅当目标属性不是null
时,如何配置自动映射
诸如此类:
Mapper.CreateMap<Item, ItemViewModel>()
.ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true))
现在是用法示例。我有一个ItemViewModel
类,我想将它映射到Item
类
映射配置:
Mapper.CreateMap<Item, ItemViewModel>()
.ForMember(x => x.Details, _ => _.UseDestinationValue())
由于存在UseDestinationValue
,AutoMapper将离开项.Details
实例,并仅设置项.Details.Info
属性
项。详细信息属性为空。现在我希望AutoMapper不要使用这个空实例,而是创建一个新实例。问题是如何配置映射以考虑这种情况
逻辑如下所示:
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);
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
)
Details
属性的类型不是:ItemDetails
,而是itemDetailsHibernateProxy
——因此,当我以后要将此现有对象保存到数据库时,必须使用此类型。但是如果这个属性是null
,那么我不能使用空的目标值,所以Automapper应该创建一个新实例
谢谢,
克里斯我认为
NullSubstitute
选项适合您。见:
编辑
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; }
}
看起来您可能需要在映射中添加一些条件逻辑以了解详细信息(并跳过UseDestinationValue
选项):
.ForMember(d=>d.详细信息,
o=>o.MapFrom(s=>s.Details==null?new ItemDetails():Mapper.Map(s.Details))
我在处理NHibernate实体时遇到了同样的问题,我找到了非常简单的解决方案
您应该在ItemViewModel构造函数中初始化Details属性。这样,目标值就永远不会为null。当然,这在更复杂的情况下(如抽象类)不起作用。也有同样的问题,但EF.Cryss关于使用BeforeMap的注释为我指明了正确的方向 我最终得到的代码类似于: 在Configure()方法中:
Mapper.CreateMap<ItemViewModel, Item>()
.AfterMap((s, d) => { MapDetailsAction(s, d); })
.ForMember(dest => dest.Details, opt => opt.UseDestinationValue());
Mapper.CreateMap()
.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);
}
};
Action-MapDetailsAction=(源、目标)=>
{
if(destination.Details==null)
{
destination.Details=新细节();
目的地,详情=
地图绘制者(
来源、详细信息、目的地、详细信息);
}
};
那么,如果UseDestinationValue为null,您是否希望执行UseDestinationValue以外的操作?是的,当destination属性为null时,我还想执行其他操作。您能否提供一些工作示例代码,说明您希望映射的内容与Auotmapper当前的操作。我只是不明白您的要求。我希望automapper使用destination属性然后设置ItemDetails类的内部属性。但这应该只在Details属性不为null时起作用(因为我想使用此实例),因此,当Details属性为null时,不要使用此null值,而是创建一个新实例。很遗憾,不是。现在我要做的是检查BeforeMap操作中的目标属性值是否为null。源值为null时,NullSubstitute很有用。
Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
{
if (destination.Details == null)
{
destination.Details = new Details();
destination.Details =
Mapper.Map<ItemViewModel, Item>(
source.Details, destination.Details);
}
};