2011-10-15 18 views
37

Empecé a usar https://github.com/robconery/massive para un proyecto, me pregunto si hay alguna herramienta de mapeo que permita la compatibilidad con el mapeo dinámico a estático.Permitir el mapeo de tipos dinámicos usando AutoMapper o similar?

He utilizado AutoMapper anteriormente, ¿lo soporta AutoMapper?

Conozco la función DynamicMap de AutoMapper, sin embargo, creo que esta función es para ejecutar mapas sin crear primero el mapa. En mi ejemplo a continuación, no funciona.

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

Ver [este q] (http://stackoverflow.com/questions/19529178/recursively-mapping-expandoobject) para una respuesta más completa. – nawfal

+0

@LiamB, "¿AutoMapper es compatible con esto?" ¿Quiere decir mapeo automático entre propiedades con nombres iguales/similares? ¿O su mapeo es más complejo? –

+0

@LeonidVasilyev Lo siento, no estoy seguro, ¡esta pregunta tiene 4 años! :) – LiamB

Respuesta

58

AutoMapper 4.2.0 ahora soporta Dynamic/expando/dictionary mapping

Con esta función se pueden asignar a los objetos expando a tipos estáticos:

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

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

antiguas de AutoMapper no apoyan esta (Massive utiliza internamente ExpandoObject que no proporciona las propiedades que tiene), y tiene razón Mapper.DynamicMap es para mapeo sin crear una configuración de mapeo.

En realidad no es difícil escribir un mapeador mismo si lo que desea el mapeo simple:

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

He estado luchando con esto durante horas esta tarde +1. Gracias – abarr

+4

@nemesv "[...] ExpandoObject que no proporciona las propiedades que tiene) [...]" <--- ExpandoObject implementa 'IDictionary ' para que pueda transmitir a esta interfaz y usar 'ContainsKey'. –

17

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

Slapper.AutoMapper los mapas de datos dinámicos a tipos estáticos

Funciona tanto para dynamic como para Dictionary<A, B> que es increíble.

He aquí un ejemplo (tomado de la URL anterior) que muestra la facilidad con que trabaja con diccionario:

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

Esto funciona con jerarquías profundas, pero aah .. la convención '_' es un fastidio ... :( – nawfal

+0

convención de nomenclatura de prueba actualizada ...;) –

+1

nooooooooo, no quise decir el nombre de su método. Quiero decir, esta es una biblioteca que trabajará con jerarquías profundas en la estructura de clases (estructura de clase compleja a diferencia del ejemplo en su respuesta) a diferencia de la respuesta aceptada, pero requiere una cierta "convención de nomenclatura" para funcionar. Vea el enlace para un ejemplo. – nawfal

3

Suponiendo marco utiliza retornos ExpandoObject que puede lograr algún tipo de mapeo dinámico utilizando 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); 

Usted puede crear cualquier tipo de análisis de complejos usando métodos ConstructUsing ..

Cuestiones relacionadas