AutoMapper

AutoMapper用于两个对象间的映射,通常用于完成DTO(Data Transfer Object)和Model之间的转换。AutoMapper

1.创建

Mapper.Initialize(cfg => {
    cfg.CreateMap<Foo, FooDto>();
    cfg.CreateMap<Bar, BarDto>();
});

var fooDto = Mapper.Map<FooDto>(foo);
var barDto = Mapper.Map<BarDto>(bar);
//通常一个AppDomain只需要一个MapperConfiguration,并且在应用程序启动时实例化
var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());

var mapper = config.CreateMapper();
// or
var mapper = new Mapper(config);
OrderDto dto = mapper.Map<OrderDto>(order);

2.Flattening(扁平化)

映射时,将源对象上的property和method与目标对象的property进行匹配。如果目标对象上的property在原对象上没有匹配的property,method或以Get开头的method,AutoMapper会以PascalCase命名约定把目标对象的成员名称分割成单词中间加点,然后进行匹配。

public class Customer
{
   public string Name { get; set; }
}

public class Product
{
    public decimal Price { get; set; }
    public string Name { get; set; }
}

public class OrderItem
{
    public Product Product { get; set; }
    //数量
    public int Quantity { get; set; }

    public OrderItem(Product p, int quantity)
    {
        Product = p;
        Quantity = quantity;
    }
    public decimal GetTotal()
    {
        return Quantity * Product.Price;
    }
}

public class Order
{
    private readonly IList<OrderItem> _orderItems = new List<OrderItem>();
    public string OrderName { get; set; }
    public Customer Customer { get; set; }

    public Order(string name)
    {
        OrderName = name;
    }  
    public OrderItem[] GetOrderItems()
    {
        return _orderItems.ToArray();
    }
    public void AddOrderItem(Product p, int num)
    {
        _orderItems.Add(new OrderItem(p, num));
    }
    public decimal GetTotal()
    {//订单总额
        return _orderItems.Sum(item => item.GetTotal());
    }
    public int Count()
    {//产品总数
        return _orderItems.Sum(item => item.Quantity);
    }
}

public class OrderDTO
{
    //对应Order.OrderName,在Order里面有同名的,直接映射
    public string OrderName { get; set; }
    //对应Order.Customer.Name,在Order里面找不到,按pascalCase拆分后再映射
    public string CustomerName { get; set; }
    //对应Order.GetTotal(),没有对于的属性/方法,但有Get开头的对应方法
    public decimal Total { get; set; }
    //对应Order.Count(),没有对应的属性或以Get开头的方法,但有同名的method
    public int Count { get; set; }
    //没有对应的属性/方法/以Get开头的方法,结果为null
    public string Address { get; set; }
}

//测试代码如下:

//products
var apple = new Product { Name = "apple", Price = 2.0m };
var pear = new Product { Name = "pear", Price = 10m };
//customer
var customer = new Customer() { Name = "Micheal" };
//order
var order = new Order("myOrder") { Customer = customer };           
order.AddOrderItem(apple, 15);
order.AddOrderItem(pear, 5);

//config map
AutoMapper.Mapper.Initialize(x => x.CreateMap<Order, OrderDTO>());

//execute map
var dto = AutoMapper.Mapper.Map<OrderDTO>(order);
//var dto1 = AutoMapper.Mapper.Map<Order, OrderDTO>(order);
//
System.Diagnostics.Trace.WriteLine(dto.OrderName + ", " + dto.CustomerName + 
    ", total: " + dto.Total + ", count: " + dto.Count);


//执行结果:
myOrder, Micheal, total: 80.0, count: 20

3.Reverse Mapping and Unflattening

反向映射通过ReverseMap来实现,而反向平坦化也只能通过ReverseMap来实现。Unflattening is only configured for ReverseMap. If you want unflattening, you must configure Entity -> Dto then call ReverseMap to create an unflattening type map configuration from the Dto -> Entity.

public class Customer
{
    public string Name { get; set; }
}

public class Order
{
    public decimal Total { get; set; }
    public Customer Customer { get; set; }
}

public class OrderDto
{
    public decimal Total { get; set; }
    public string CustomerName { get; set; }
}

//测试代码:
//双向映射
Mapper.Initialize(cfg => {
    cfg.CreateMap<Order, OrderDto>()//正向
       .ReverseMap();//反向
});

var customer = new Customer { Name = "Bob" };
var order = new Order { Customer = customer, Total = 15.8m };
//正向及其反转
//Order -> OrderDto
var orderDto = Mapper.Map<Order, OrderDto>(order);
System.Diagnostics.Trace.WriteLine(orderDto.CustomerName + ", " + orderDto.Total);//Bob, 15.8
//orderDto -> order
orderDto.CustomerName = "Joe";
Mapper.Map(orderDto, order);
System.Diagnostics.Trace.WriteLine(order.Customer.Name + ", " + order.Total);//Joe, 15.8

//反向及其反转
//OrderDto -> Order
var orderDto1 = new OrderDto { CustomerName = "micheal", Total = 88 };
var order1 = Mapper.Map<Order>(orderDto1);
System.Diagnostics.Trace.WriteLine(order1.Customer.Name + ", " + order1.Total);//micheal, 88
//order1 -> orderDto1
order1.Total = 8;
Mapper.Map(order1, orderDto1);
System.Diagnostics.Trace.WriteLine(orderDto1.CustomerName + ", " + orderDto1.Total);//micheal, 8

4.Customizing reverse mapping

//前面的例子看到AutoMapper会自动把Customer.Name从CustomerName反向映射
//如果使用MapFrom自定义映射,AutoMapper也会尝试将其反向映射,只要MapFrom的path是成员访问器。
Mapper.Initialize(cfg => {
    cfg.CreateMap<Order, OrderDto>()
       .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
       .ReverseMap();
});
//测试代码同上一例,结果完全相同。

如果需要自定义反转映射,那么可以使用ForPath。
For most cases you shouldn’t need this, as the original MapFrom will be reversed for you. Use ForPath when the path to get and set the values are different.

cfg.CreateMap<Order, OrderDto>()
    //自定义映射规则,反向转换时会自定按这个反转映射
    .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
    .ReverseMap()
    //如果要自定义反转规则,那么就要用ForPath来改变,下面是语法上的示例
    .ForPath(s => s.Customer.Name, opt => opt.MapFrom(src => src.CustomerName));

If you do not want unflattening behavior, you can remove the call to ReverseMap and create two separate maps. Or, you can use Ignore:

cfg.CreateMap<Order, OrderDto>()
    .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
    .ReverseMap()
    .ForPath(s => s.Customer.Name, opt => opt.Ignore());

5.Projection(投影)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值