zoukankan      html  css  js  c++  java
  • AutoMapper

    DTO即数据传输对象。

    简单来说Model面向业务,我们是通过业务来定义Model的。而DTO是面向界面UI,是通过UI的需求来定义的。通过DTO我们实现了表现层与Model之间的解耦,表现层不引用Model,如果开发过程中我们的模型改变了,而界面没变,我们就只需要改Model而不需要去改表现层中的东西。

    一、最简单的用法

    有两个类User和UserDto

    public class User
        {
             public int Id { get; set; }
             public string Name { get; set; }
             public int Age { get; set; }
         }
     
         public class UserDto
         {
             public string Name { get; set; }
             public int Age { get; set; }
         }

    将User转换成UserDto也和简单

    Mapper.Initialize(x => x.CreateMap<User, UserDto>());
     User user = new User()
      {
          Id = 1,
           Name = "caoyc",
          Age = 20
       };
    var dto = Mapper.Map<UserDto>(user);

     这是一种最简单的使用,AutoMapper会根据字段名称去自动对于,忽略大小写。

    二、如果属性名称不同

    将UserDto的Name属性改成Name2

    Mapper.Initialize(x => 
         x.CreateMap<User, UserDto>()
          .ForMember(d =>d.Name2, opt => {
             opt.MapFrom(s => s.Name);
              })
        );
       User user = new User()
       {
          Id = 1,
          Name = "caoyc",
          Age = 20
       };
     var dto = Mapper.Map<UserDto>(user);

    三、使用Profile配置

    自定义一个UserProfile类继承Profile,并重写Configure方法

     public class UserProfile : Profile
      {
        protected override void Configure()
          {
             CreateMap<User, UserDto>().ForMember(d => d.Name2, opt =>
                {
                    opt.MapFrom(s => s.Name);
               });
           }
    }

    使用时就这样

    Mapper.Initialize(x => x.AddProfile<UserProfile>());
       User user = new User()
      {
         Id = 1,
         Name = "caoyc",
         Age = 20
      };
    var dto = Mapper.Map<UserDto>(user);

    四、空值替换NullSubstitute

    空值替换允许我们将Source对象中的空值在转换为Destination的值的时候,使用指定的值来替换空值。

    public class UserProfile : Profile
     {
         protected override void Configure()
         {
                   CreateMap<User, UserDto>()
                     .ForMember(d => d.Name2, opt => opt.MapFrom(s => s.Name))
                     .ForMember(d => d.Name2, opt => opt.NullSubstitute("值为空"));              
         }
     }
    Mapper.Initialize(x => x.AddProfile<UserProfile>());
       User user = new User()
        {
            Id = 1,
             Age = 20
        };
     var dto = Mapper.Map<UserDto>(user);

    结果为:

    五、忽略属性Ignore

    public class User
     {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
     }
     public class UserDto
     {
            public string Name { get; set; }
            public int Age { get; set; }
    }
    public class UserProfile : Profile
    {
            protected override void Configure()
            {
                 CreateMap<User, UserDto>().ForMember("Name", opt => opt.Ignore());
            } 
    }

    使用

    Mapper.Initialize(x => x.AddProfile<UserProfile>());
    User user = new User()
    {
         Id = 1,
         Name="caoyc",
         Age = 20
    };
    var dto = Mapper.Map<UserDto>(user);

    结果:

    六、预设值

    如果目标属性多于源属性,可以进行预设值

    public class User
    {
          public int Id { get; set; }
          public string Name { get; set; }
          public int Age { get; set; }
    }
    public class UserDto
    {
          public string Name { get; set; }
          public int Age { get; set; }
          public string Gender { get; set; }
    }
    public class UserProfile : Profile
    {
          protected override void Configure()
          {
             CreateMap<User, UserDto>();
          }
    }

    使用

    Mapper.Initialize(x => x.AddProfile<UserProfile>());
     User user = new User()
    {
          Id = 1,
          Name="caoyc",
          Age = 20
    };
    UserDto dto = new UserDto() {Gender = "男"};
    Mapper.Map(user, dto);

     七、类型转换ITypeConverter

    如果数据中Gender存储的int类型,而DTO中Gender是String类型

    public class User
    {
            public int Gender { get; set; }
     }
    public class UserDto
    {
           public string Gender { get; set; }
    }

    类型转换类,需要实现接口ITypeConverter

    public class GenderTypeConvertert : ITypeConverter<int, string>
    {
          public string Convert(int source, string destination, ResolutionContext context)
          {
              switch (source)
              {
                      case 0:
                           destination = "";
                           break;
                      case 1:
                           destination = "";
                           break;
                      default:
                           destination = "未知";
                           break;
               }
               return destination;
          }
    }

    配置规则

    public class UserProfile : Profile
    {
         protected override void Configure()
         {
                CreateMap<User, UserDto>();
                CreateMap<int, string>().ConvertUsing<GenderTypeConvertert>();
                //也可以写这样
                //CreateMap<int, string>().ConvertUsing(new GenderTypeConvertert());
         }
    }

    使用

    Mapper.Initialize(x => x.AddProfile<UserProfile>());
    User user0 = new User() { Gender = 0 };
    User user1 = new User() { Gender = 1 };
    User user2 = new User() { Gender = 2 };
    var dto0= Mapper.Map<UserDto>(user0);
    var dto1 = Mapper.Map<UserDto>(user1);
    var dto2 = Mapper.Map<UserDto>(user2);
    
    Console.WriteLine("dto0:{0}", dto0.Gender);
    Console.WriteLine("dto1:{0}", dto1.Gender);
    Console.WriteLine("dto2:{0}", dto2.Gender);

    结果

    八、条件约束Condition

    当满足条件时才进行映射字段,例如人类年龄,假设我们现在人类年龄范围为0-200岁(这只是假设),只有满足在这个条件才进行映射

    public class User
    {
            public int Age { get; set; }
    }
    
    public class UserDto
    {
            public int Age { get; set; }
    }

    Profile

    public class UserProfile : Profile
    {
         protected override void Configure()
         {
              CreateMap<User, UserDto>().ForMember(dest=>dest.Age,opt=>opt.Condition(src=>src.Age>=0 && src.Age<=200));
         }
    }

    使用代码

    Mapper.Initialize(x => x.AddProfile<UserProfile>());
    User user0 = new User() { Age = 1 };
    User user1 = new User() { Age = 150 };
    User user2 = new User() { Age = 201 };
    var dto0= Mapper.Map<UserDto>(user0);
    var dto1 = Mapper.Map<UserDto>(user1);
    var dto2 = Mapper.Map<UserDto>(user2);
    
    Console.WriteLine("dto0:{0}", dto0.Age);
    Console.WriteLine("dto1:{0}", dto1.Age);
    Console.WriteLine("dto2:{0}", dto2.Age);

    输出结果

    倘若在项目中真正要用的时候,我觉得还是应该对AutoMapper的方法进行一些整理,最好能够封装一下,这里我通过扩展方法的形式将其封装为AutoMapperHelper,这样以后使用AutoMapper就变的SO EASY了~

    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using AutoMapper;
    namespace Infrastructure.Utility
    
    {
        /// <summary>
        /// AutoMapper扩展帮助类
        /// </summary>
        public static class AutoMapperHelper
        {
            /// <summary>
            ///  类型映射
            /// </summary>
            public static T MapTo<T>(this object obj)
            {
                if (obj == null) return default(T);
                Mapper.CreateMap(obj.GetType(), typeof(T));
                return Mapper.Map<T>(obj);
            }
            /// <summary>
            /// 集合列表类型映射
            /// </summary>
            public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
            {
                foreach (var first in source)
                {
                    var type = first.GetType();
                    Mapper.CreateMap(type, typeof(TDestination));
                    break;
                }
                return Mapper.Map<List<TDestination>>(source);
            }
            /// <summary>
            /// 集合列表类型映射
            /// </summary>
            public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
            {
                //IEnumerable<T> 类型需要创建元素的映射
                Mapper.CreateMap<TSource, TDestination>();
                return Mapper.Map<List<TDestination>>(source);
            }
            /// <summary>
            /// 类型映射
            /// </summary>
            public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
                where TSource : class
                where TDestination : class
            {
               if (source == null) return destination;
                Mapper.CreateMap<TSource, TDestination>();
                return Mapper.Map(source, destination);
            }
            /// <summary>
            /// DataReader映射
            /// </summary>
            public static IEnumerable<T> DataReaderMapTo<T>(this IDataReader reader)
            {
                Mapper.Reset();
                Mapper.CreateMap<IDataReader, IEnumerable<T>>();
                return Mapper.Map<IDataReader, IEnumerable<T>>(reader);
            }
        }
    }

    你可以像下面的栗子这样使用:

    //对象映射
    ShipInfoModel  shipInfoModel =  ShipInfo.MapTo<ShipInfoModel>();
    //列表映射
    List< ShipInfoModel > shipInfoModellist = ShipInfoList.MapToList<ShipInfoModel>();
  • 相关阅读:
    0593. Valid Square (M)
    0832. Flipping an Image (E)
    1026. Maximum Difference Between Node and Ancestor (M)
    0563. Binary Tree Tilt (E)
    0445. Add Two Numbers II (M)
    1283. Find the Smallest Divisor Given a Threshold (M)
    C Primer Plus note9
    C Primer Plus note8
    C Primer Plus note7
    C Primer Plus note6
  • 原文地址:https://www.cnblogs.com/sylone/p/9450464.html
Copyright © 2011-2022 走看看