web-dev-qa-db-fra.com

Créez deux cartes Automapper entre les deux mêmes types d'objet

J'utilise AutoMapper dans un service WCF pour renvoyer des objets User. User a des propriétés telles que AccountTeams qui elle-même a des objets enfants. Toutes les classes ont des cartes AutoMapper.

Selon le WCF OperationContract qui est appelé, je souhaite renvoyer différentes quantités de données. Je veux qu'un OperationContract retourne l'objet User sans sa propriété AccountTeams (et leurs enfants) renseignée et un autre OperationContract pour retourner le User avec toute la chaîne de propriétés remplie.

Existe-t-il un moyen d'avoir deux mappages différents entre les deux mêmes objets ou dois-je effectuer le mappage complet et null les propriétés que je ne veux pas retourner du service?

33
Kevin Kalitowski

Kevin Kalitowski a soulevé un bon point à propos de la réponse de wal: Si nous avons besoin de deux configurations pour traiter un mappage qui doit être différent, ne devons-nous pas dupliquer tous les autres mappages qui sont communs?

Je pense que j'ai trouvé un moyen de contourner cela en utilisant des profils: avoir un profil pour chacun des mappages uniques et un troisième profil pour les mappages communs. Créez ensuite deux configurations, une pour chaque profil unique, mais ajoutez également le profil commun à chaque configuration.

Exemple, dans AutoMapper 4.2:

Les classes à cartographier: Utilisateur et véhicule:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Vehicle
{
    public int FleetNumber { get; set; }
    public string Registration { get; set; }
}

Les profils:

public class Profile1 : Profile
{
    protected override void Configure()
    {
        base.CreateMap<User, User>();
    }
}

public class Profile2 : Profile
{
    protected override void Configure()
    {
        base.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
    }
}

public class CommonProfile : Profile
{
    protected override void Configure()
    {
        base.CreateMap<Vehicle, Vehicle>();
    }
}

Créez ensuite les configurations et mappez les objets:

[TestMethod]
public void TestMethod()
{
    var user = new User() { Name = "John", Age = 42 };
    var vehicle = new Vehicle {FleetNumber = 36, Registration = "XYZ123"};

    var configuration1 = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<CommonProfile>();
        cfg.AddProfile<Profile1>();
    });

    var mapper1 = configuration1.CreateMapper();
    var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
    var mappedVehicle1 = mapper1.Map<Vehicle, Vehicle>(vehicle);//Maps both FleetNumber 
                                                                //and Registration.

    var configuration2 = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<CommonProfile>();
        cfg.AddProfile<Profile2>();
    });

    var mapper2 = configuration2.CreateMapper();
    var mappedUser2 = mapper2.Map<User, User>(user);//maps only Name
    var mappedVehicle2 = mapper2.Map<Vehicle, Vehicle>(vehicle);//Same as mappedVehicle1.
}

J'ai essayé et ça marche.

13
Simon Tewsi

Je suppose que vous mappez de User à User (sinon, changez simplement le type de destination)

Supposons cette classe pour l'exemple suivant:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Vous pouvez ensuite utiliser un AutoMapper.Configuration pour définir 2 cartes:

[TestMethod]
public void TestMethod()
{
    var configuration1 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
    var mapper1 = new MappingEngine(configuration1);
    configuration1.CreateMap<User, User>();

    var user = new User() { Name = "John", Age = 42 };
    var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age

    var configuration2 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
    configuration2.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
    var mapper2 = new MappingEngine(configuration2);

    var mappedUser2 = mapper2.Map<User, User>(user);
    Assert.AreEqual(0, mappedUser2.Age);//maps only Name
}

Pour éviter de mapper deux fois tous les autres types, vous pouvez ajouter une méthode courante qui prend un Configuration qui mappe tout ce qui peut être atteint à partir de User et l'appeler sur les deux configuration1 et configuration2 après les appels à CreateMap.

Mise à jour

Pour Automapper 4.x, utilisez les éléments suivants:

var configuration1 = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, User>();
});

var mapper1 = configuration1.CreateMapper();
var user = new User() { Name = "John", Age = 42 };
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age

var configuration2 = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
});

var mapper2 = configuration2.CreateMapper();
var mappedUser2 = mapper2.Map<User, User>(user);   //maps only Name
15
wal

Je pense que vous pouvez résoudre ce problème avec différents objets de configuration comme décrit ici , vous pouvez en trouver un exemple ici

1
mrtentje