2011-10-15 12 views
37

Ho iniziato a utilizzare https://github.com/robconery/massive per un progetto, mi chiedo se esiste uno strumento di mappatura che consente il supporto per il mapping di tipo statico dinamico?Permetti il ​​mapping di tipi dinamici usando AutoMapper o simili?

Ho usato AutoMapper in precedenza, AutoMapper supporta questo?

Sono a conoscenza della funzione DynamicMap di AutoMapper, tuttavia ritengo che questa funzione sia per l'esecuzione di mappe senza prima creare la mappa. Nel mio esempio qui sotto non funziona.

dynamic curUser = users.GetSingleUser(UserID); 
var retUser = Mapper.DynamicMap<UserModel>(curUser); 
users.GetSingleUser(UserID); // returns a dynamic object 
+0

Sede [questo q] (http://stackoverflow.com/questions/19529178/recursively-mapping-expandoobject) per una risposta più completa. – nawfal

+0

@LiamB, "AutoMapper supporta questo?" - intendi una mappatura automatica tra proprietà con nomi uguali/simili? O la tua mappatura è più complessa? –

+0

@LeonidVasilyev Siamo spiacenti, non sono sicuro, questa domanda ha 4 anni! :) – LiamB

risposta

58

AutoMapper 4.2.0 ora supporta Dynamic/expando/dictionary mapping

Con questa funzione è possibile associare agli oggetti expando ai tipi statici:

dynamic CurUser = _users.GetSingleUser(UserID); 
var config = new MapperConfiguration(cfg => { }); 
var mapper = config.CreateMapper(); 

var retUser = mapper.Map<UserModel>(CurUser); 

Le vecchie versioni di automapper non supportano questa (utilizza Massive internamente ExpandoObject che non fornisce le proprietà che ha), e hai ragione: Mapper.DynamicMap è per il mapping senza creare la configurazione del mapping.

In realtà non è difficile scrivere voi stessi un mapper se si desidera solo semplice mappatura:

public static class DynamicToStatic 
{ 
    public static T ToStatic<T>(object expando) 
    { 
     var entity = Activator.CreateInstance<T>(); 

     //ExpandoObject implements dictionary 
     var properties = expando as IDictionary<string, object>; 

     if (properties == null) 
      return entity; 

     foreach (var entry in properties) 
     { 
      var propertyInfo = entity.GetType().GetProperty(entry.Key); 
      if(propertyInfo!=null) 
       propertyInfo.SetValue(entity, entry.Value, null); 
     } 
     return entity; 
    } 
} 

dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = DynamicToStatic.ToStatic<UserModel>(CurUser); 
+0

Sono stato alle prese con questo per ore questo pomeriggio +1. Grazie – abarr

+4

@nemesv "[...] ExpandoObject che non fornisce le proprietà che ha) [...]" <--- ExpandoObject implements 'IDictionary ' in modo da poter trasmettere a questa interfaccia e utilizzare 'ContainsKey'. –

17

Prova Slapper.AutoMapperhttps://github.com/randyburden/Slapper.AutoMapper

Slapper.AutoMapper associa i dati dinamici ai tipi statici

Funziona sia per dynamic e Dictionary<A, B> che è fantastico.

Ecco un esempio (tratto dal URL sopra) che mostra quanto facilmente funziona con il dizionario:

public class Person 
{ 
    public int Id; 
    public string FirstName; 
    public string LastName; 
} 

[Test] 
public void CanMapMatchingFieldNamesWithEase() 
{ 
    // Arrange 
    var dictionary = new Dictionary<string, object> 
          { 
           { "Id", 1 }, 
           { "FirstName", "Clark" }, 
           { "LastName", "Kent" } 
          }; 

    // Act 
    var person = Slapper.AutoMapper.Map<Person>(dictionary); 

    // Assert 
    Assert.NotNull(person); 
    Assert.That(person.Id == 1); 
    Assert.That(person.FirstName == "Clark"); 
    Assert.That(person.LastName == "Kent"); 
} 
+0

Questo funziona con gerarchie profonde, ma aah .. la convenzione '_' è un bummer .. :( – nawfal

+0

convenzione di denominazione dei test aggiornata ...;) –

+1

nooooooooo, non intendevo il nome del tuo metodo. Intendevo dire, questa è una libreria che funzionerà con gerarchie profonde nella struttura delle classi (struttura di classi complesse a differenza dell'esempio nella risposta) a differenza della risposta accettata, ma richiede una certa "convenzione di denominazione" per funzionare. Vedi il link per un esempio. – nawfal

3

Supponendo quadro si utilizza rendimenti ExpandoObject si possono ottenere una sorta di mappatura dinamica utilizzando automapper:

Mapper.CreateMap<ExpandoObject, UserModel>() 
    .ForAllMembers((options) => options.ResolveUsing((resolution) => 
     { 
      var dictionary = (IDictionary<string, object>) resolution.Context.SourceValue; 
      return dictionary[resolution.Context.MemberName]; 
     })); 
... 
dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = Mapper.Map<UserModel>(CurUser); 

È possibile creare qualsiasi tipo di mappatura complesso utilizzando metodi ConstructUsing ..

Problemi correlati