2012-05-09 18 views
5

tengo un usuario Dictionary<User, bool>Diccionario AutoMapper aplanamiento

es el siguiente:

public class User { 
    public string Username { get; set; } 
    public string Avatar { get; set; 
} 

El segundo tipo, bool, indica si el usuario es un amigo del usuario conectado. quiero para aplanar este Diccionario en una List<UserDto> UserDto se define como:

public class UserDto { 
    public string Username { get; set; } 
    public string Avatar { get; set; } 
    public bool IsFriend { get; set; } 
} 

IsFriend representa el valor del diccionario.

¿Cómo puedo hacer esto?

+0

Si alguien me puede dar un método que realmente utiliza automapper, voy a cambiar la respuesta a la pregunta! – reach4thelasers

Respuesta

11

usted debería ser capaz de hacer esto con sólo un mapeo :

tendrá que asignar un KeyValuePair<User, bool> a UserDto. Esto es necesario para que AutoMapper pueda asignar los contenidos del diccionario a los contenidos del List<T> que finalmente estamos creando (se puede encontrar más de una explicación en this answer).

Mapper.CreateMap<KeyValuePair<User, bool>, UserDto>() 
    .ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.Key.UserName)) 
    .ForMember(dest => dest.Avatar, opt => opt.MapFrom(src => src.Key.Avatar)) 
    .ForMember(dest => dest.IsFriend, opt => opt.MapFrom(src => src.Value)); 

A continuación, utilice la asignación en su llamada .Map:

Mapper.Map<Dictionary<User, bool>, List<UserDto>>(...); 

No es necesario mapear las colecciones a sí mismos, como AutoMapper puede manejar el mapeo de la Dictionary a un List, siempre y cuando' ve asignado el contenido de las colecciones entre sí (en nuestro caso, KeyValuePair<User, bool> a UserDto).


Editar: Aquí hay otra solución que no requiere la cartografía de cada User propiedad a UserDto:

Mapper.CreateMap<User, UserDto>(); 
Mapper.CreateMap<KeyValuePair<User, bool>, UserDto>() 
    .ConstructUsing(src => Mapper.Map<User, UserDto>(src.Key)) 
    .ForMember(dest => dest.IsFriend, opt => opt.MapFrom(src => src.Value)); 

Usando AutoMapper 2.0

+0

Esta solución requiere que cada vez que agregue una propiedad a User & UserDto necesito cambiar la asignación. Prefiero tener una solución que no requiera el mapeo de propiedades individuales. No se trata de cómo se supone que funciona el automapper. – reach4thelasers

+1

Si "no se supone que funcione el Automapper", ¿por qué la API incluso proporciona un método '.ForMember'? Sin embargo, intentaré una solución más "automática". –

+1

@ reach4thelasers: He agregado otra solución que creo que podría ser un poco más automatica. –

-1

Para algo simple como este, una consulta rápida de LINQ servirá. Suponiendo dict es su Dictionary<User,bool>:

var conv = from kvp in dict 
      select new UserDto 
        { 
         Avatar = kvp.Key.Avatar, 
         IsFriend = kvp.Value, 
         Username = kvp.Key.Username 
        }; 
0

Sé que llego tarde para el juego, sin embargo, esta parece ser una solución más genérica para mapear un diccionario a un tipo .Net (si MPLE) usando AutoMapper

public static IMappingExpression<Dictionary<string, string>, TDestination> ConvertFromDictionary<TDestination>(
     this IMappingExpression<Dictionary<string, string>, TDestination> exp) 
{ 
    foreach (PropertyInfo pi in typeof(TDestination).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) 
    { 
     exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[propertyName])); 
    } 
    return exp; 
} 

utilizar de esta manera

Mapper.CreateMap<Dictionary<string, string>, TDestination>().ConvertFromDictionary(); 

donde TDestination puede un tipo simple .NET. Para tipos complejos, puede suministrar un delegado Func/Action y un mapa usando esa función. (Dentro de la anterior para cada uno)

P. ej.

if (customPropNameMapFunc != null && !string.IsNullOrEmpty(customPropNameMapFunc(propertyName))) 
{ 
    exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[customPropNameMapFunc(propertyName)])); 
}