web-dev-qa-db-fra.com

Autoriser le mappage de types dynamiques avec AutoMapper ou similaire?

J'ai commencé à utiliser https://github.com/robconery/massive pour un projet. Je me demande s'il existe un outil de mappage permettant de prendre en charge le mappage de type dynamique/statique? 

J'ai déjà utilisé AutoMapper. Est-ce qu'AutoMapper prend cela en charge?

Je connais la fonction DynamicMap d’AutoMapper, mais j’estime que cette fonction permet d’exécuter des cartes sans créer d’abord la Carte. Dans mon exemple ci-dessous, cela ne fonctionne pas.

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

AutoMapper 4.2.0 supporte maintenant Mappage dynamique/expando/dictionary

Avec cette fonctionnalité, vous pouvez mapper vos objets expando sur des types statiques:

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

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

Les anciennes versions d'AutoMapper ne prennent pas cela en charge (Massive utilise en interne ExpandoObject qui ne précise pas les propriétés dont il dispose), et vous avez raison, Mapper.DynamicMap permet d'effectuer un mappage sans créer de configuration. 

En fait, écrire un mappeur n’est pas difficile si vous voulez juste un mappage simple:

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);
66
nemesv

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

Slapper.AutoMapper mappe des données dynamiques à des types statiques

Cela fonctionne à la fois pour dynamic et Dictionary<A, B>, ce qui est génial.

Voici un exemple (tiré de l'URL ci-dessus) montrant avec quelle facilité il fonctionne avec Dictionary:

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" );
}
17
Tod Thomson

En supposant que la structure que vous utilisez renvoie ExpandoObject, vous pouvez réaliser une sorte de mappage dynamique à l'aide d'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);

Vous pouvez créer tout type de mappage complexe à l'aide des méthodes ConstructUsing.

3
Leonid Vasilev

Objet unique:

Mapper.Map<Product>(dynamicProduct);

Liste:

Mapper.Map<List<Product>>(dynamicListOfProducts);

Exemple (ligne 71): https://github.com/AutoMapper/AutoMapper/blob/master/src/UnitTests/DynamicMapping.cs

0
JedatKinports