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>();
  • 相关阅读:
    Heroku
    Git基本命令(转)
    github之从零开发
    物理层、、。。。
    BeautifulSoup, 的使用
    路径设置
    http协议
    Python 的os模块与sys模块
    python 操作MySQL数据库
    多进程记要
  • 原文地址:https://www.cnblogs.com/sylone/p/9450464.html
Copyright © 2011-2022 走看看