web-dev-qa-db-fra.com

AutoMapper vs ValueInjecter

Chaque fois que je cherche AutoMapper sur StackOverflow, je lis quelque chose à propos de ValueInjecter .

Quelqu'un peut-il me dire le pour et le contre entre eux (performances, fonctionnalités, utilisation de l'API, extensibilité, tests)?

209
Rookian

en tant que créateur de ValueInjecter , je peux vous dire que je l'ai fait parce que je voulais quelque chose simple et très flexible

Je n'aime vraiment pas beaucoup écrire ou écrire beaucoup de monkey code Comme:

Prop1.Ignore, Prop2.Ignore etc.
CreateMap<Foo,Bar>(); CreateMap<Tomato, Potato>(); etc.

ValueInjecter est quelque chose comme mozilla avec ses plugins, vous créez ValueInjections et les utilisez

il y a des injections intégrées pour aplatir, sans aplatir, et certaines sont destinées à être héritées

et cela fonctionne plus dans un type d'aspect , vous n'avez pas besoin de spécifier toutes les propriétés 1-à-1, vous faites plutôt quelque chose comme:

prend toutes les propriétés int de la source dont le nom se termine par "Id", transforme la valeur et définit chacune une propriété de l'objet source portant le même nom sans le suffixe Id et dont le type est hérité d'Entity.

donc une différence évidente, ValueInjecter est utilisé même dans les formulaires Windows avec une mise à plat et une mise à plat, c'est à quel point il est flexible

(mappage d'objet à des contrôles de formulaire et retour)

Automapper, non utilisable dans les formulaires Windows, pas unflatenning, mais il a de bonnes choses comme le mappage de collections, donc au cas où vous en auriez besoin avec ValueInjecter, vous feriez juste quelque chose comme:

foos.Select(o => new Bar().InjectFrom(o));

vous pouvez également utiliser ValueInjecter pour mapper des objets anonymes et dynamiques

différences:

  • automapper crée une configuration pour chaque possibilité de mappage CreateMap ()

  • valueinjecter injecte n'importe quel objet dans n'importe quel objet (il y a aussi des cas où vous injectez un objet à un autre)

  • automapper a mis à plat construit, et seulement pour les types simples ou du même type, et il n'a pas unflattening

  • valueinjecter seulement si vous en avez besoin, vous faites target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> et si vous voulez de Foo.Bar.Name of type String à FooBarName of type Class1, vous héritez de FlatLoopValueInjection et le spécifiez

  • automapper mappe les propriétés avec le même nom par défaut et pour le reste, vous devez spécifier un par un, et faire des choses comme Prop1.Ignore (), Prop2.Ignore (), etc.

  • valueinjecter a une injection par défaut .InjectFrom () qui effectue les propriétés avec le même nom et le même type; pour tout le reste, vous créez vos valeurs personnalisées avec des règles/règles de mappage individuelles, ressemblant davantage à des aspects, par exemple de tous les accessoires du type Foo à tous les accessoires du type Bar

170
Omu

N'ayant jamais utilisé aucun des autres outils, je ne peux parler que d'AutoMapper. J'avais quelques objectifs en tête pour créer AutoMapper:

  • Prise en charge des objets DTO stupides
  • Prend en charge des scénarios évidents prêts à l'emploi (collections, énumérations, etc.)
  • Être capable de vérifier facilement les correspondances dans un test
  • Autoriser les cas Edge à résoudre les valeurs d'autres emplacements (mappage type-> type personnalisé, mappage de membre individuel et certains cas Edge vraiment fous).

Si vous voulez faire ces choses, AutoMapper fonctionne très bien pour vous. Les choses que AutoMapper ne fait pas bien sont:

  • Remplir des objets existants
  • Unflattening

La raison étant que je n'ai jamais eu besoin de faire ces choses. La plupart du temps, nos entités n'ont pas de setters, n'exposent pas de collections, etc., c'est pourquoi elles ne sont pas là. Nous utilisons AutoMapper pour réduire les DTO et mapper à partir de modèles d’interface utilisateur pour commander des messages, etc. C'est là que ça fonctionne vraiment, vraiment bien pour nous.

59
Jimmy Bogard

J'ai essayé les deux et je préfère ValueInjecter parce que c'est si simple:

myObject.InjectFrom(otherObject);

C'est tout ce qu'il y a à savoir pour la grande majorité de mes besoins d'injection. Il ne peut pas devenir plus simple et élégant que cela.

55
Adrian Grigore

C’est une question sur laquelle j’ai également fait des recherches, et pour mon cas d’utilisation, il semble que ce soit un investisseur de valeur. Il ne nécessite aucune configuration préalable (les performances risquent d’être médiocres, mais si elles étaient intelligemment implémentées, les mappages pourraient être mis en cache pour les invocations futures au lieu d’être reflétés à chaque fois). Il n’est donc pas nécessaire de prédéfinir ces mappages avant de les utiliser.

Plus important encore, il permet la cartographie inversée. Il se peut que je manque quelque chose ici car Jimmy mentionne qu'il ne voit aucun cas d'utilisation nécessaire, alors le modèle est peut-être erroné, mais mon cas d'utilisation est que je crée un objet ViewModel à partir de mon ORM. Je l’affiche ensuite sur ma page Web. Une fois que l'utilisateur a terminé, je récupère ViewModel en tant que httppost, comment est-il reconverti en classes ORM d'origine? J'aimerais connaître le modèle avec automapper. Avec ValueInjector, c'est trivial, et ça va même unflatten. par exemple, créer une nouvelle entité

Le modèle créé par l'entitéframework (modèle en premier):

public partial class Family
{ 
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public virtual Address Address { get; set; }
}

public partial class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string TownCity { get; set; }
    public string County { get; set; }
    public string Postcode { get; set; }

    public virtual Family Family { get; set; }
}

Le ViewModel (que je peux décorer avec des validateurs):

public class FamilyViewModel
{
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public int AddressId { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string AddressTownCity { get; set; }
    public string AddressCounty { get; set; }
    public string AddressPostcode { get; set; }
}

Le ViewController:

    //
    // GET: /Family/Create

    public ActionResult Create()
    {
        return View();
    } 

    //
    // POST: /Family/Create

    [HttpPost]
    public ActionResult Create(FamilyViewModel familyViewModel)
    {
        try
        {
            Family family = new Family();
            family.InjectFrom<UnflatLoopValueInjection>(familyViewModel);
            db.Families.Add(family);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

À mon avis, cela ne devient pas beaucoup plus simple que cela?

(Cela pose donc la question suivante: qu'est-ce qui ne va pas avec le schéma que je rencontre (et il semble que beaucoup d'autres le font), qu'il n'est pas considéré comme ayant une valeur pour AutoMapper?)

Cependant, si vous voulez utiliser ce modèle décrit, alors mon vote est valueinjecter par un pays.

27
DanH