2013-11-21 16 views
5

ho mappature definite in questo modo:automapper - fortemente tipizzato set di dati

Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>(); 

Il MyRowDto è di 1: 1 copia di TMyRow ma tutte le proprietà sono le proprietà auto.

[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; 
    } 
} 

quando chiamo:

DsMyDataSet.TMyRow row = ....; 
AutoMapper.Mapper.Map<MyRowDto>(row); 

ottengo l'eccezione StrongTypingException perché il valore della colonna è nullo. La proprietà è nullable ma i set di dati fortemente tipizzati non supportano le proprietà nullable e devi chiamare IsNullable instea. Come aggirare questo problema in AutoMapper in modo tale che i mapping superino (ignorando l'errore e lasciando il valore nullo)?

risposta

2

Penso che il modo più semplice per risolvere questo problema è quello di utilizzare il metodo IMemberConfigurationExpression<DsMyDataSet.TMyRow>.Condition() e utilizzare un blocco try-catch per verificare se l'accesso alla valore di origine lancia un StrongTypingException.

Ecco cosa il vostro codice finirebbe per assomigliare:

Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>() 
     .ForMember(target => target.PositionFolder, 
     options => options.Condition(source => { 
      try { return source.PositionFolder == source.PositionFolder; } 
      catch(StrongTypingException) { return false; } 
     }); 

Se questo è un evento comune, allora avete alcune altre opzioni per evitare di scrivere tutto il codice per ogni membro.

Un modo è quello di utilizzare un metodo di estensione:

Mapper 
.CreateMap<Row,RowDto>() 
.ForMember(target => target.PositionFolder, options => options.IfSafeAgainst<Row,StrongTypingException>(source => source.PositionFolder)) 

quando il seguente è nella soluzione:

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 ha anche qualche costruito in punti di estendibilità che potrebbe essere sfruttato anche qui . Un paio di possibilità che saltano fuori di me sono:

  1. Definire una IValueResolver un'implementazione personalizzata. Esiste già un'implementazione simile nella soluzione che è possibile utilizzare: NullReferenceExceptionSwallowingResolver. Probabilmente potresti copiare quel codice e poi cambiare la parte che specifica il tipo di eccezione con cui stai lavorando. Documentation for configuration is on the AutoMapper wiki, ma il codice di configurazione sarebbe simile:

    Mapper.CreateMap<Row,RowDto>() 
        .ForMember(target => target.PositionFolder, 
         options => options.ResolveUsing<ExceptionSwallowingValueResolver<StrongTypingException>>()); 
    
2

Utilizzare questa mappatura:

Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>() 
    .ForMember(s => s.PositionFolder, o => o.MapFrom(d => !d.IsPositionFolderNull() ? d.PositionFolder: null)); 
Problemi correlati