Разрешить отображение динамических типов с помощью AutoMapper или аналогичного?
Я начал использовать https://github.com/robconery/massive для проекта, интересно, есть ли какой-либо инструмент отображения, который позволяет поддерживать динамическое статическое тип отображения?
Я использовал AutoMapper ранее, поддерживает ли AutoMapper это?
Мне известно о функции DynamicMap из AutoMapper, однако я считаю, что эта функция предназначена для запуска карт, не создавая сначала карту. В моем примере ниже это не работает.
dynamic curUser = users.GetSingleUser(UserID);
var retUser = Mapper.DynamicMap<UserModel>(curUser);
users.GetSingleUser(UserID); // returns a dynamic object
Ответы
Ответ 1
AutoMapper 4.2.0 теперь поддерживает Динамический/expando/отображение словарей
С помощью этой функции вы можете сопоставить объекты 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);
Ответ 2
Попробуйте Slapper.AutoMapper https://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" );
}
Ответ 3
Предполагая, что вы используете return 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
.