In modern applications, especially MVC, MVVM, and MVP applications, it’s all too common to run into situations where you need to map data or properties from one object to another. Writing code to tackle this manually is not only tedious, but prone to simple—yet costly—mistakes. Happily, though, there are a number of open-source libraries that developers can easily leverage to help take the sting out of mapping. In this post, I’ll briefly touch upon two libraries that I happen to enjoy quite a bit, ValueInjecter and AutoMapper.
The Need for Mapping
Without much effort, I can think of at least three particularly common scenarios where mapping is necessary in many apps being created today.
View Models: With MVC, MVVM, and MVP applications, the notion of using view models as a means of letting users interact with data and objects is a powerful paradigm, which you only have to use for a little while before you start to see tangible benefits. There is, however, the drawback that view models are very similar to the actual models that they present or display to users— meaning that you’ll commonly end up with the need to map data back and forth between models and view models and vice versa. Technically speaking, you could argue that the presence of view models violates the 'don't repeat yourself (DRY)' principle through the creation of multiple classes with, effectively, many of the same properties or data. But it’s also arguable that view models facilitate the single responsibility principle (SRP) by representing an object whose sole responsibility is to handle interactions with users, which is my take. When used, though, view models frequently result in the need for mapping.
Data Transfer Objects (DTOs): I’m just not a big fan of DTOs. Part of it has to do with the fact that bumping into classes with names like UserDTO or AccountDTO feels too much like an analog of Hungarian Notation. (Don’t ask me, though, why I have no problem with class names like SignupViewModel or UserViewModel.) The bigger issue, however, is that when it comes to database/datastore interactions, I really prefer my data code to work directly with "plain-old" CLR objects (POCOs). DTOs just seem too, well, enterprise-like to me—or too much like we’ve only met the database/datastore half-way. Still, the use of DTOs, even if they may not always be named as such, is fairly common and, as such, there are cases where mapping is going to be needed.
API Interactions: For applications that interact with or communicate with other applications or services, it’s pretty common to represent data from other systems as objects. In my experience, those objects rarely represent a perfect one-to-one match with the kinds of objects you’ll typically be dealing with in your own application when you’re either consuming or interacting with other systems via APIs. As such, you’ll commonly want or need some sort of mapping functionality that lets you move data from external to internal objects and vice versa when working with APIs.
A Tale of Two Paradigms— for Two Different Mapping Needs
I’ve actually known about AutoMapper for years now. In fact, I remember when it was launched; I remember thinking that it’d be a great way to get around some of the manual coding I’d been doing to tackle the need for mapping. The crazy thing is, as of a few weeks ago, I still hadn’t even started using AutoMapper. Ultimately, I think the biggest hindrance in using AutoMapper, other than the fact that I haven’t done a lot of mapping until recently, was the notion of having to define a mapping configuration somewhere. To me, that bit of overhead just seemed to take all the fun out of the party. If I have to write or detail mappings anyhow, then that’s hardly any different from what I’ve been doing previously with extension methods (defined once) that were manually tackling mapping for me already.
Consequently, when I accidentally stumbled into ValueInjecter on a closed StackOverflow question (I swear that all of the best info on StackOverflow is found in questions that over-zealous moderators have closed), I was instantly intrigued. In fact, after perusing a few examples, and literally exclaiming out loud, I actually had ValueInjecter wired up into my most recent application.
A few minutes later, I then came full-circle, seeing exactly why ValueInjecter is not a replacement for AutoMapper. I also came face-to-face with a clearer understanding of why one of these solutions simply can’t be better than the other, and that’s because they both take entirely different approaches to mapping data. In short, ValueInjecter’s elegance and simplicity stems from its ability to simply iterate over properties and data within one class and automatically map those onto the properties of the targeted class whenever the property names and types are the same. ValueInjecter can also tackle some kinds of flattening (i.e., ParentClass_PropertyName) for deeper object graphs, but can’t and won’t tackle ‘non-conventional’ mappings or mappings where property names simply don’t match up.
For example, with ValueInjecter, if I’ve got two classes and they each have a .HashedPassword property, then ValueInjecter will seamlessly and elegantly map that property data for me as needed. On the other hand, if the both classes have a property designed to serve as the same concept, but one of the classes calls that property a .PasswordHash, then the convention-based approach to how ValueInjecter works is busted and the property data won’t be mapped. Consequently, something like AutoMapper is needed, where I’ll have to actually set up mappings and TELL my code that a .PasswordHash maps to a .HashedPassword if I want data to be mapped or transferred across. AutoMapper will, of course, handle simple convention-based mappings right out of the box without the need for explicit mappings, but AutoMapper's strength lies in the fact that you CAN provide it with the configuration details needed to tackle explicit mappings.
Somehow, I wasn’t thinking correctly when I jumped at the chance to use ValueInjecter—thinking that it would somehow be exponentially easier to use than AutoMapper. If all of my mapping involved classes with identical property names, then ValueInjecter would be the clear-cut winner. But since that hardly ever happens, there’s still a strong need for AutoMapper. In turn, that means there’s still a need to define that pesky mapping—there’s obviously no way around it. Ironically, I wasn’t actually able to realize why AutoMapper is as great as it is until I started using ValueInjecter.