Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMapper vs ValueInjecter [closed]

as the creator of ValueInjecter, I can tell you that I did it because I wanted something simple and very flexible

I really don't like writing much or writing lots of monkey code like:

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

ValueInjecter is something like mozilla with it's plugins, you create ValueInjections and use them

there are built-in injections for flattening, unflattening, and some that are intended to be inherited

and it works more in an aspect type of way, you don't have to specify all properties 1-to-1, instead you do something like:

take all the int properties from source which name ends with "Id", transform the value and set each to a property in the source object with same name without the Id suffix and it's type is inherited from Entity, stuff like that

so one obvious difference, ValueInjecter is used even in windows forms with flattening and unflattening, that's how flexible it is

(mapping from object to form controls and back)

Automapper, not usable in windows forms, no unflatenning, but it has good stuff like collections mapping, so in case you need it with ValueInjecter you just do something like:

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

you can also use ValueInjecter to map from anonymous and dynamic objects

differences:

  • automapper create configuration for each mapping possibility CreateMap()

  • valueinjecter inject from any object to any object (there are also cases when you inject from object to valuetype)

  • automapper has flattening built it, and only for simple types or from same type, and it doesn't has unflattening

  • valueinjecter only if you need it you do target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> and if you want from Foo.Bar.Name of type String to FooBarName of type Class1 you inherit FlatLoopValueInjection and specify this

  • automapper maps properties with same name by default and for the rest you have to specify one by one, and do stuff like Prop1.Ignore(), Prop2.Ignore() etc.

  • valueinjecter has a default injection .InjectFrom() that does the properties with the same name and type; for everything else you create your custom valueinjections with individual mapping logic/rules, more like aspects, e.g. from all props of Type Foo to all props of type Bar


Since I've never used any of the other tools, I can only talk about AutoMapper. I had a few goals in mind for building AutoMapper:

  • Support flattening to dumb DTO objects
  • Support obvious scenarios out of the box (collections, enumerations etc.)
  • Be able to easily verify mappings in a test
  • Allow for edge cases for resolving values from other places (custom type->type mapping, individual member mapping, and some really crazy edge cases).

If you want to do these things, AutoMapper works very well for you. Things AutoMapper doesn't do well are:

  • Filling existing objects
  • Unflattening

The reason being I've never needed to do these things. For the most part, our entities don't have setters, don't expose collections, etc. so that's why it's not there. We use AutoMapper to flatten to DTOs and map from UI models to command messages and the like. That's where it works really, really well for us.


I tried both and prefer ValueInjecter because it's so simple:

myObject.InjectFrom(otherObject);

That's all there is to know for the vast majority of my injection needs. It can't possibly get more simple and elegant than this.


This is a question I've been researching too, and for my use case, it seems to be valueinjecter hands down. It requires no prior setup to use (may hit performance I guess, although if smartly implemented it could cache the mappings for future invocations rather than reflecting each time), so you don't need to predefine any mappings before using them.

Most importantly however, it allows reverse mapping. Now I may be missing something here as Jimmy mentions that he sees no use case where its necessary, so maybe I have the pattern wrong, but my use case is that I'm creating a ViewModel object from my ORM. I then display this on my webpage. Once the user finishes I get the ViewModel back in as a httppost, how does this get converted back to the original ORM classes? I'd love to know the pattern with automapper. With ValueInjector it is trivial, and it will even unflatten. e.g Creating a new entity

The model created by the entityframework (model first):

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; }
}

The ViewModel (which I can decorate with validators):

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; }
}

The 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();
        }
    }

To my mind, it doesn't get much simpler than that?

(So this begs the question, whats wrong with the pattern that I run into this (and it seems many others do to), that its not seen as of value to AutoMapper?)

However, if this pattern as decscribed, is one you want to use, then my vote is valueinjecter by a country mile.