2017-01-18 2 views
2

У меня есть настройки карты:Как создать родовое отображение с AutoMapper и ConstructUsing

Mapper.Initialize(cfg => 
{ 
    cfg.CreateMap<IDictionary<int, MyType1>, List<MyType1>>().ConstructUsing(
     x0 => x0?.OrderBy(x => x.Key).Select(x => x.Value).ToList()); 
}); 

Как я могу изменить это, чтобы работать с «все MyTypes»?

Я хочу, чтобы конвертировать из IDictionary<int, T> в List<T> для любого типа T.

Я нашел очень некрасиво решение:

cfg.CreateMap(typeof(IDictionary<,>), typeof(List<>)).ConstructUsing(
    x0 => 
    { 
     if (x0 == null) 
     { 
      return null; 
     } 

     var dict = (IEnumerable)x0; 
     var type = x0.GetType().GetGenericArguments()[1]; 
     var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type)); 
     CastDictionaryEntry(dict).OrderBy(x => x.Key).ForEach(x => list.Add(x.Value)); 
     return list; 
    } 
); 

и:

static IEnumerable<DictionaryEntry> CastDictionaryEntry(IEnumerable dict) 
{ 
    foreach (var item in dict) 
    { 
     yield return (DictionaryEntry)item; 
    } 
} 

Есть ли более простой способ сделать это?

+0

Что случилось с 'dict.Values'? –

+0

Я хочу сортировать dict.Values ​​по ключу в списке результатов. , так что если Dictionalry содержит: {1, "a"}, {3, "b"}, {2, "c"}, результат должен быть {"a", "c", "b"}, а не случайным , Вторая проблема заключается в том, что IEnumerable не имеет свойства Values. Как я могу получить доступ к свойству «Значения» IDictionary ? – zgabi

+0

Я не могу отдать его IDictionary (не общий), потому что мой объект Dictionary не является IDictionary (например, PersistentGenericMap NHibernate) – zgabi

ответ

0

Я думаю, что работает, но опять же я не тестировал против широкого набора ВВОДА

class ABC 
    { 
     public int MyProperty { get; set; } 
     public int MyProperty2 { get; set; } 
    } 
    static List<T> ConfigureMap<T>(Dictionary<int, T> input) where T : class 
    { 
     AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap(input.GetType(), typeof(List<T>)) 
     .ConstructUsing(Construct)); 

     return Mapper.Map<List<T>>(input); 

    } 

    private static object Construct(object arg1, ResolutionContext arg2) 
    { 
     if (arg1 != null) 
     { 
      var val = arg1 as IDictionary; 
      var argument = val.GetType().GetGenericArguments()[1]; 
      if (val != null) 
      { 
       var type = Activator.CreateInstance(typeof(List<>).MakeGenericType(argument)); 

       foreach (var key in val.Keys) 
       { 
        ((IList)type).Add(val[key]); 
       } 

       return type; 
      } 
     } 

     return null; 
    } 

var so = new Dictionary<int, ABC> { { 1, new ABC { MyProperty = 10, MyProperty2 = 30 } } }; 
var dest = new List<ABC>(); 
var res = ConfigureMap<ABC>(so); 
+0

В этом случае словарь не сортируется, и это решение не проще. Reflection и Activaror.Creatinstance все еще необходимо. Я думаю, что это решение сложнее, чем мое решение. – zgabi

+0

Другая проблема заключается в том, что «val» всегда будет null, потому что мой объект не IDictionary, это только IDictionary Единственный базовый не общий интерфейс, который я могу использовать, это IEnumerable – zgabi

Смежные вопросы