AutoMapper is an object-object mapper for D like C# AutoMapper.
It use compile-time generated mapper to try to avoid any overhead.
You can run the benchmark located in tests/benchmark
:
$ cd tests/benchmark
$ dub test
This project is well documented:
$ dub build --build=ddox
import std.stdio;
import automapper;
class Order
{
Customer customer;
Product product;
}
class Product
{
float price;
string name;
}
class Customer
{
string name;
string city;
string email;
}
class OrderDTO
{
string customerName;
string customerCity;
string customerEmail;
float productPrice;
string productName;
}
auto makeOrder()
{
auto order = new Order();
order.customer = new Customer();
order.customer.name = "boolangery";
order.customer.city = "Annecy";
order.customer.email = "[email protected]";
order.product = new Product();
order.product.price = 42;
order.product.name = "universe";
return order;
}
void main()
{
// create a compile-time generated mapper to map from Order to OrderDTO,
// and from OrderDTO to Order.
auto mapper = MapperConfiguration!(
CreateMap!(Order, OrderDTO)
.ReverseMap!())
.createMapper();
auto initial = makeOrder();
auto dto = mapper.map!OrderDTO(initial); // map Order to OrderDTO
auto order = mapper.map!Order(dto); // map back OrderDTO to Order
assert(order.customer.name == initial.customer.name);
assert(order.customer.city == initial.customer.city);
assert(order.customer.email == initial.customer.email);
assert(order.product.price == initial.product.price);
assert(order.product.name == initial.product.name);
// more suitable runtime mapper
RuntimeAutoMapper m = mapper.createRuntimeContext();
}
To be as fast as possible, AutoMapper do by deafult all its magic at compile-time (See example bellow). Mapping check are static asserted.
It implies that AutoMapper type is specialized using templates:
alias AM = AutoMapper!(MapperConfiguration!(CreateMap!(Order, OrderDTO, ReverseMapConfig)));
AM mapper = MapperConfiguration!(
CreateMap!(Order, OrderDTO)
.ReverseMap!())
.createMapper();
It may be difficult to pass this complex object along your framework. Its why you can use a slower version, that check things at runtime.
The example above became:
RuntimeAutoMapper mapper = MapperConfiguration!(
CreateMap!(Order, OrderDTO)
.ReverseMap!())
.createMapper()
.createRuntimeContext();
import automapper;
import std.datetime;
class A {
long timestamp;
}
class B {
SysTime timestamp;
}
auto am = MapperConfiguration!(
CreateMap!(long, SysTime)
.ConvertUsing!((long ts) => SysTime(ts)),
CreateMap!(A, B))
.createMapper();