/src/AutoMapper/Mappers/DictionaryMapper.cs

https://github.com/rpg1503/AutoMapper · C# · 66 lines · 49 code · 14 blank · 3 comment · 4 complexity · 56196738db0d3ae0655ce2b47aef6fe1 MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using AutoMapper.Internal;
  6. namespace AutoMapper.Mappers
  7. {
  8. // So IEnumerable<T> inherits IEnumerable
  9. // but IDictionary<TKey, TValue> DOES NOT inherit IDictionary
  10. // Fiddlesticks.
  11. public class DictionaryMapper : IObjectMapper
  12. {
  13. private static readonly Type KvpType = typeof(KeyValuePair<,>);
  14. public bool IsMatch(ResolutionContext context)
  15. {
  16. return (context.SourceType.IsDictionaryType() && context.DestinationType.IsDictionaryType());
  17. }
  18. public object Map(ResolutionContext context, IMappingEngineRunner mapper)
  19. {
  20. if (context.IsSourceValueNull && mapper.ShouldMapSourceCollectionAsNull(context))
  21. return null;
  22. var sourceEnumerableValue = (IEnumerable)context.SourceValue ?? new object[0];
  23. IEnumerable<object> keyValuePairs = sourceEnumerableValue.Cast<object>();
  24. Type genericSourceDictType = context.SourceType.GetDictionaryType();
  25. Type sourceKeyType = genericSourceDictType.GetGenericArguments()[0];
  26. Type sourceValueType = genericSourceDictType.GetGenericArguments()[1];
  27. Type sourceKvpType = KvpType.MakeGenericType(sourceKeyType, sourceValueType);
  28. Type genericDestDictType = context.DestinationType.GetDictionaryType();
  29. Type destKeyType = genericDestDictType.GetGenericArguments()[0];
  30. Type destValueType = genericDestDictType.GetGenericArguments()[1];
  31. var dictionaryEntries = keyValuePairs.OfType<DictionaryEntry>();
  32. if (dictionaryEntries.Any())
  33. keyValuePairs = dictionaryEntries.Select(e => Activator.CreateInstance(sourceKvpType, e.Key, e.Value));
  34. object destDictionary = ObjectCreator.CreateDictionary(context.DestinationType, destKeyType, destValueType);
  35. int count = 0;
  36. foreach (object keyValuePair in keyValuePairs)
  37. {
  38. object sourceKey = sourceKvpType.GetProperty("Key").GetValue(keyValuePair, new object[0]);
  39. object sourceValue = sourceKvpType.GetProperty("Value").GetValue(keyValuePair, new object[0]);
  40. TypeMap keyTypeMap = mapper.ConfigurationProvider.FindTypeMapFor(sourceKey, null, sourceKeyType, destKeyType);
  41. TypeMap valueTypeMap = mapper.ConfigurationProvider.FindTypeMapFor(sourceValue, null, sourceValueType, destValueType);
  42. ResolutionContext keyContext = context.CreateElementContext(keyTypeMap, sourceKey, sourceKeyType, destKeyType, count);
  43. ResolutionContext valueContext = context.CreateElementContext(valueTypeMap, sourceValue, sourceValueType, destValueType, count);
  44. object destKey = mapper.Map(keyContext);
  45. object destValue = mapper.Map(valueContext);
  46. genericDestDictType.GetMethod("Add").Invoke(destDictionary, new[] { destKey, destValue });
  47. count++;
  48. }
  49. return destDictionary;
  50. }
  51. }
  52. }