簡體   English   中英

AutoMapper - 強類型數據集

[英]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 也有一些內置的可擴展點,也可以在這里利用。 我想到的幾種可能性是:

  1. 定義自定義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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM