Reputation: 8067
I'm having a problem with one of my automapping configurations that I can't seem to solve.
I have an entity of type contact and I'm trying to map a list of these to a dictionary. However, the mapping just doesn't do anything. The source dictionary remains empty. Can anyone offer any suggestions?
Below is a simplified version of the Contact type
public class Contact
{
public Guid Id { get; set ;}
public string FullName { get; set; }
}
My automapping configuration looks as follows
Mapper.CreateMap<Contact, KeyValuePair<Guid, string>>()
.ConstructUsing(x => new KeyValuePair<Guid, string>(x.Id, x.FullName));
And my calling code looks as follows
var contacts = ContactRepository.GetAll(); // Returns IList<Contact>
var options = new Dictionary<Guid, string>();
Mapper.Map(contacts, options);
Upvotes: 2
Views: 7702
Reputation: 15026
Another solution in GitHub AutoMapper:
https://github.com/AutoMapper/AutoMapper/issues/51
oakinger[CodePlex] just wrote a small extension method that solves this:
public static class IMappingExpressionExtensions
{
public static IMappingExpression<IDictionary, TDestination> ConvertFromDictionary<TDestination>(this IMappingExpression<IDictionary, TDestination> exp, Func<string, string> propertyNameMapper)
{
foreach (PropertyInfo pi in typeof(Invoice).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (!pi.CanWrite ||
pi.GetCustomAttributes(typeof(PersistentAttribute), false).Length == 0)
{
continue;
}
string propertyName = pi.Name;
propertyName = propertyNameMapper(propertyName);
exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[propertyName]));
}
return exp;
}
}
Usage:
Mapper.CreateMap<IDictionary, MyType>()
.ConvertFromDictionary(propName => propName) // map property names to dictionary keys
Upvotes: 0
Reputation: 50523
This should work with the following, no Mapper needed...
var dictionary = contacts.ToDictionary(k => k.Id, v => v.FullName);
Upvotes: 10
Reputation: 56779
The documentation is very sketchy on the AutoMapper website. From what I can tell, the second parameter in Mapper.Map
is used only to determine what type the return value should be, and is not actually modified. This is because it allows you to perform dynamic mapping based on an existing object whose type is only known at runtime instead of hard-coding a type in the generics.
So the problem in your code is that you are not making use of the return value of Mapper.Map
, which actually contains the final converted object. Here is a modified version of your code that I've tested and correctly returns the converted objects as you expect.
var contacts = ContactRepository.GetAll();
var options = Mapper.Map(contacts, new Dictionary<Guid, string>());
// options should now contain the mapped version of contacts
Although it would be more efficient to take advantage of the generic version instead of constructing an unnecessary object just to specify the type:
var options = Mapper.Map<List<Contact>, Dictionary<Guid, string>>(contacts);
Here is a working code sample that can be run in LinqPad (an assembly reference to AutoMapper.dll is needed to run the sample.)
Hope this helps!
Upvotes: 5