[英]AutoMapper - strongly typed data set
我有這樣定義的映射:
Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>();
MyRowDto 是 TMyRow 的 1:1 副本,但所有屬性都是自動屬性。
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
public string PositionFolder{
get {
try {
return ((string)(this[this.tableTMyDataSet.PositionFolderColumn]));
}
catch (global::System.InvalidCastException e) {
throw new global::System.Data.StrongTypingException("The value for column \'PositionFolder\' in table \'TMyDataSet\' is DBNull.", e);
}
}
set {
this[this.tableTMyDataSet.PositionFolderColumn] = value;
}
}
當我打電話時:
DsMyDataSet.TMyRow row = ....;
AutoMapper.Mapper.Map<MyRowDto>(row);
我收到 StrongTypingException 異常,因為列中的值為空。 該屬性可為空,但強類型數據集不支持可為空的屬性,您必須調用 IsNullable instea。 我如何在 AutoMapper 中解決這個問題,以便映射繼續進行(忽略錯誤並保留空值)?
使用此映射:
Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>()
.ForMember(s => s.PositionFolder, o => o.MapFrom(d => !d.IsPositionFolderNull() ? d.PositionFolder: null));
我認為解決這個問題的最簡單方法是使用IMemberConfigurationExpression<DsMyDataSet.TMyRow>.Condition()
方法並使用try-catch
塊來檢查訪問源值是否會引發StrongTypingException
。
這是您的代碼最終的樣子:
Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>()
.ForMember( target => target.PositionFolder,
options => options.Condition(source => {
try { return source.PositionFolder == source.PositionFolder; }
catch(StrongTypingException) { return false; }
});
如果這種情況很常見,那么您還有其他一些選擇來避免為每個成員編寫所有這些代碼。
一種方法是使用擴展方法:
Mapper
.CreateMap<Row,RowDto>()
.ForMember( target => target.PositionFolder, options => options.IfSafeAgainst<Row,StrongTypingException>(source => source.PositionFolder) )
當解決方案中有以下內容時:
public static class AutoMapperSafeMemberAccessExtension
{
public static void IfSafeAgainst<T,TException>(this IMemberConfigurationExpression<T> options, Func<T,object> get)
where TException : Exception
{
return options.Condition(source => {
try { var value = get(source); return true; }
catch(TException) { return false; }
});
}
}
AutoMapper 也有一些內置的可擴展點,也可以在這里利用。 我想到的幾種可能性是:
定義自定義IValueResolver
實現。 您可以使用的解決方案中已經有一個類似的實現: NullReferenceExceptionSwallowingResolver
。 您可能會復制該代碼,然后更改指定您正在使用的異常類型的部分。 配置文檔位於 AutoMapper wiki 上,但配置代碼如下所示:
Mapper.CreateMap<Row,RowDto>() .ForMember( target => target.PositionFolder, options => options.ResolveUsing<ExceptionSwallowingValueResolver<StrongTypingException>>());
在較新版本的 Automapper 中,如果DataRow
屬性為DBNull
,則通常可以通過使用IMemberConfigurationExpression<TSource, TDestination, TMember>.PreCondition()
來防止它們被映射:
var config = new MapperConfiguration(
cfg =>
{
cfg.CreateMap<DsMyDataSet.TMyRow, MyRowDto>();
cfg.ForAllMaps((typeMap, map) =>
{
map.ForAllMembers(opt =>
{
opt.PreCondition((src, context) =>
{
var row = src as DataRow;
if (row != null)
{
return !row.IsNull(opt.DestinationMember.Name);
}
return true;
});
});
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.