📜 ⬆️ ⬇️

Have you prepared for the coming AutoMapper?

Introduction

This article is intended to be read by developers and architects of distributed systems on the .NET platform. It will consider the flexible framework for object-object transformation (further mapping). Some aspects of Domain-Driven Design will also be considered.

Why do I need object-object mapping?

Following the basic principles of DDD , we implement the so-called Rich Domain Model (these objects must also comply with the POxO principle). Objects of the real world that are reflected in our application often also convey sufficient complexity, therefore, a fairly well-constructed model is extremely difficult to move between layers of the application (not to be confused with the ease of the changes). Data Transfer Object Nevertheless, quite often there is a need for “distribution” (I mean the creation of intermediate entities, rather than the model spreading over layers) between layers to display, for example, attributes of its entities to users (in MVx presentation templates ), as well as transfer by services ( Data Transfer Object ). Sometimes it even happens that the model is “distributed” to test some aspects. Suppose we are in Africa, we have a banana plantation, everything is cool, we grow, we sell, we grow, we sell, but then the domestic market suddenly becomes overwhelmed and we need to expand (for example, we will send bananas to Russia), we will write a WCF service that our bananas. Since bananas in Africa have a slightly different meaning than in Russia, then, accordingly, we will need only some attributes (the rest actually do not matter), which we will perish in our DTO
It would be more correct to give the BananaWrapper class the name BananaDTO, in order to accurately reflect its functional purpose, but I will leave this name for a higher level of abstraction, for example, if we need to make a banana machine and place this object in the Presenter Model
I want to note that sometimes the task of transforming objects becomes quite non-trivial and at best looks something like this (this solution head-on, there are even more sophisticated methods;)):
public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  1. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  2. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  3. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  4. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  5. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  6. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  7. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  8. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  9. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  10. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  11. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  12. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  13. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  14. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  15. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  16. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  17. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  18. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  19. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  20. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  21. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  22. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  23. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  24. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  25. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  26. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  27. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  28. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
  29. public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
public class Banana { public string Country { get ; set ; } public double Price { get ; set ; } public double NationalTax { get ; set ; } public bool CocaineInjection { get ; set ; } public bool FreshForFooding { get ; set ; } public string AkunamatataName { get ; set ; } public string BananaGeneration { get ; set ; } public int Age { get ; set ; } } public class BananaWrapper { public string Country { get ; set ; } public double Price { get ; set ; } public int Age { get ; set ; } } public class BananaMapper { public BananaWrapper GetWrapper(Banana banana) { return new BananaWrapper { Country = banana.Country, Price = banana.Price, Age = banana.Age }; } } * This source code was highlighted with Source Code Highlighter .
I think that this code will be a joy to write, and even more so to accompany, recently I have often met with such tasks recently, and was looking for a solution to the problem.

Automap

And then our character, AutoMapper , comes on the scene and immediately says to me: - Listen, what are you writing? are you not lazy? Are you not afraid to make mistakes? Do you want me to help you?! .. Of course, I agree, and in return I get the following solution to my problem:
  1. public class BananaMapper
  2. {
  3. public BananaMapper ()
  4. {
  5. Mapper.CreateMap <Banana, BananaWrapper> ();
  6. }
  7. public BananaWrapper GetWrapper (Banana banana)
  8. {
  9. return Mapper.Map <Banana, BananaWrapper> (banana); ;
  10. }
  11. }
* This source code was highlighted with Source Code Highlighter .
Class, and that's really all I need. The complexity of the overlying example has dropped to zero in my eyes. So, what kind of mechanisms lie inside AutoMapper? AutoMapper checks there are corresponding fields in the specified types, the match is carried out both by the name of the property and by its type. Even nuances such as Product.Name and ProductName will be taken into account and processed automatically (wow!). Plus, the GetXXX () methods will fall on the XXX properties (yes, and of course, for particularly irritable ones, all these charms can be disabled and redefined everything in their own correspondence tables (hereafter)). The custom configuration looks like this:
  1. Mapper.CreateMap <CalendarEvent, CalendarEventForm> ()
  2. .ForMember (dest => dest.EventDate, opt => opt.MapFrom (src => src.EventDate.Date))
  3. .ForMember (dest => dest.EventHour, opt => opt.MapFrom (src => src.EventDate.Hour))
  4. .ForMember (dest => dest.EventMinute, opt => opt.MapFrom (src => src.EventDate.Minute));
* This source code was highlighted with Source Code Highlighter .
By the way, all your custom configurations are easy to verify using the following method:
  1. Mapper.AssertConfigurationIsValid ();
* This source code was highlighted with Source Code Highlighter .
It also does not work badly with:

Story

The project appeared at the end of '08 and early '09, was in version 0.31 for about half a year, now I got to RC 1.0, I think that the release is very soon.

Overhead?

banana Debate about how much faster AutoMapper will work and the manual assignment of properties (and other mulks) I ignore, because ready to make any sacrifice of performance if I get a clear, readable code. Oh yes, the author of AutoMapper took care of these issues and wrote benchmarks, look here: http://code.google.com/p/automapperhome/source/browse/#svn/trunk/src/Benchmark

Resources

Download the project, as well as get acquainted with the source code here: http://code.google.com/p/automapperhome/ The discussion of the framework here: http://groups.google.com/group/automapper-users Also use examples There is here: http://automapper.codeplex.com/ By the way, the project is developed by Joe Benninghoven , who also writes a BDD framework for .NET called NBehave .

')

Source: https://habr.com/ru/post/71820/


All Articles