I've got a Dictionary<User, bool>
User is as follows:
public class User {
public string Username { get; set; }
public string Avatar { get; set;
}
The second type, bool, indicates whether this user is a friend of the logged in User.
I want to flatten this Dictionary into a List<UserDto
> UserDto is defined as:
public class UserDto {
public string Username { get; set; }
public string Avatar { get; set; }
public bool IsFriend { get; set; }
}
IsFriend
represents the value of the dictionary.
How can I do this?
You should be able to do this with just one mapping1:
You need to map a KeyValuePair<User, bool>
to UserDto
. This is necessary for AutoMapper to be able to map the contents of the dictionary to the contents of the List<T>
we're ultimately creating (more of an explanation can be found in 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));
Then, use the mapping in your .Map
call:
Mapper.Map<Dictionary<User, bool>, List<UserDto>>(...);
You don't need to map the collections themselves, as AutoMapper can handle mapping the Dictionary
to a List
as long as you've mapped the contents of the collections to each other (in our case, KeyValuePair<User, bool>
to UserDto
).
Edit: Here's another solution that doesn't require mapping every User
property to 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));
1Using AutoMapper 2.0
I know I am late to the game, yet this seems to be a more generic solution for mapping a dictionary to a .Net type(simple) using 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;
}
Use it like this
Mapper.CreateMap<Dictionary<string, string>, TDestination>().ConvertFromDictionary();
where TDestination can a .NET simple type. For complex types, you could supply a Func/Action delegate and map using that function.(Inside the above for-each)
Eg.
if (customPropNameMapFunc != null && !string.IsNullOrEmpty(customPropNameMapFunc(propertyName)))
{
exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[customPropNameMapFunc(propertyName)]));
}
For something simple like this, a quick LINQ query will do. Assuming dict
is your Dictionary<User,bool>
:
var conv = from kvp in dict
select new UserDto
{
Avatar = kvp.Key.Avatar,
IsFriend = kvp.Value,
Username = kvp.Key.Username
};