2011-10-15 2 views
37

Я начал использовать https://github.com/robconery/massive для проекта, интересно, есть ли какой-либо инструмент отображения, который позволяет поддерживать динамическое сопоставление статического типа?Разрешить отображение динамических типов с помощью AutoMapper или аналогичного?

Я использовал AutoMapper ранее, поддерживает ли AutoMapper это?

Мне известно о функции DynamicMap из AutoMapper, однако я считаю, что эта функция предназначена для запуска карт без создания карты в первую очередь. В моем примере ниже это не работает.

dynamic curUser = users.GetSingleUser(UserID); 
var retUser = Mapper.DynamicMap<UserModel>(curUser); 
users.GetSingleUser(UserID); // returns a dynamic object 
+0

См [это д] (http://stackoverflow.com/questions/19529178/recursively-mapping-expandoobject) для более полного ответа. – nawfal

+0

@LiamB, «поддерживает ли AutoMapper это?» - вы имеете в виду автоматическое сопоставление свойств с равными/похожими именами? Или ваше сопоставление более сложное? –

+0

@LeonidVasilyev Извините - я не уверен, этому вопросу 4 года! :) – LiamB

ответ

58

AutoMapper 4.2.0 теперь поддерживает Dynamic/expando/dictionary mapping

С помощью этой функции вы можете привязать к вашим объектам EXPANDO для статических типов:

dynamic CurUser = _users.GetSingleUser(UserID); 
var config = new MapperConfiguration(cfg => { }); 
var mapper = config.CreateMapper(); 

var retUser = mapper.Map<UserModel>(CurUser); 

Старые версии AutoMapper не поддерживают это (Massive внутренне использует ExpandoObject, который не предоставляет какие у него свойства), и вы правы. Mapper.DynamicMap предназначен для сопоставления без создания конфигурации отображения.

На самом деле это не так трудно, чтобы написать картографа, если вы просто хотите простое отображение:

public static class DynamicToStatic 
{ 
    public static T ToStatic<T>(object expando) 
    { 
     var entity = Activator.CreateInstance<T>(); 

     //ExpandoObject implements dictionary 
     var properties = expando as IDictionary<string, object>; 

     if (properties == null) 
      return entity; 

     foreach (var entry in properties) 
     { 
      var propertyInfo = entity.GetType().GetProperty(entry.Key); 
      if(propertyInfo!=null) 
       propertyInfo.SetValue(entity, entry.Value, null); 
     } 
     return entity; 
    } 
} 

dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = DynamicToStatic.ToStatic<UserModel>(CurUser); 
+0

Я борется с этим часами сегодня днем ​​+1. Спасибо – abarr

+4

@nemesv "[...] ExpandoObject, который не предоставляет какие свойства он имеет) [...]" <--- ExpandoObject реализует 'IDictionary ', поэтому вы можете использовать этот интерфейс и использовать 'ContainsKey'. –

17

Try Slapper.AutoMapperhttps://github.com/randyburden/Slapper.AutoMapper

Slapper.AutoMapper отображает динамические данные статических типов

Он работает как для dynamic, так и для Dictionary<A, B> Это потрясающе.

Вот пример (взятый из приведенного выше URL), показывающий, как легко она работает с Словаре:

public class Person 
{ 
    public int Id; 
    public string FirstName; 
    public string LastName; 
} 

[Test] 
public void CanMapMatchingFieldNamesWithEase() 
{ 
    // Arrange 
    var dictionary = new Dictionary<string, object> 
          { 
           { "Id", 1 }, 
           { "FirstName", "Clark" }, 
           { "LastName", "Kent" } 
          }; 

    // Act 
    var person = Slapper.AutoMapper.Map<Person>(dictionary); 

    // Assert 
    Assert.NotNull(person); 
    Assert.That(person.Id == 1); 
    Assert.That(person.FirstName == "Clark"); 
    Assert.That(person.LastName == "Kent"); 
} 
+0

Это работает с глубокими иерархами, но ах .. соглашение '_' является обломком .. :( – nawfal

+0

обновленное соглашение об именовании тестов ...;) –

+1

nooooooooo, я не имел в виду имя вашего метода. Я имел в виду, что это одна библиотека, которая будет работать с глубокими иерархиями в структуре классов (сложная структура классов, в отличие от примера в вашем ответе), в отличие от принятого ответа, но для этого требуется определенное «соглашение об именах». См. Ссылку для примера. – nawfal

3

Предполагая, что рамочное вы использовать возвраты ExpandoObject вы можете достичь своего рода динамического отображения с использованием AutoMapper:

Mapper.CreateMap<ExpandoObject, UserModel>() 
    .ForAllMembers((options) => options.ResolveUsing((resolution) => 
     { 
      var dictionary = (IDictionary<string, object>) resolution.Context.SourceValue; 
      return dictionary[resolution.Context.MemberName]; 
     })); 
... 
dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = Mapper.Map<UserModel>(CurUser); 

Вы можете создать любой вид комплексного картографирования с использованием ConstructUsing методов ..

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