自制AutoMapper实现DTO到持久层Entity的转换
项目中经常涉及到页面DTO更新,保存到数据库的操作,这就必然牵扯到DTO和持久层对象的转换,常见的第三方库有:
java:dozer
.net: AutoMapper
看到AutoMapper已经许久没更新了,而且项目中没必要用这么大的东西,于是自己实现了一个简易DTO到Entity的转换器。
实现的功能
自定义的AutoMapper主要实现了如下几点功能:
1.DTO字段忽略转换
[AutoMapping(Ignore=true)] public DateTime CreateTime { get; set; }
2.DTO字段和Entity的强制映射
[AutoMapping(EntityColumn="Sex")] public string XingBie { get; set; }
3.默认DTO和Entity字段相同的,自动转换
核心代码:
using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Linq; namespace ElegantWM.AutoMapper { public class AutoMapper<T1,T2> where T1:new() where T2:new() { /// <summary> /// DTO 转换为 Entity /// </summary> /// <typeparam name="T1">DTO</typeparam> /// <typeparam name="T2">Entity</typeparam> /// <param name="t1">Dto</param> /// <param name="t2">Entity</param> /// <returns></returns> public static T2 Convert(T1 t1, T2 t2) { var dtoProperList = t1.GetType().GetProperties().Where(p => p.PropertyType.IsPublic == true).ToList(); var entityProperList = t2.GetType().GetProperties().Where(p => p.PropertyType.IsPublic == true).ToList(); foreach (System.Reflection.PropertyInfo pi in dtoProperList) { string realName=pi.Name; //首先判断列是否ignore?,是否含有Column object[] cusAttrs = pi.GetCustomAttributes(typeof(AutoMappingAttribute), true); if (cusAttrs.Length > 0) { AutoMappingAttribute attr = cusAttrs[0] as AutoMappingAttribute; if (attr.Ignore) continue; if (!string.IsNullOrEmpty(attr.EntityColumn)) realName = attr.EntityColumn; } var entityPi = entityProperList.Single(p => p.Name == realName); if (entityPi == null) continue; object value = pi.GetValue(t1, null); if (value == null) continue; entityPi.SetValue(t2, value, null); } return t2; } } }
案例
持久层Entity的定义如下:
public class Entity:IEntity { public Guid Id { get; set; } public string CreateUser { get; set; } public DateTime CreateTime { get; set; } public string ModifyUser { get; set; } public DateTime? ModifyTime { get; set; } [Timestamp] public Byte[] RowVersion { get; set; } } public class WMS_User : Entity { public WMS_User() { } public string UserName { get; set; } public string NickName { get; set; } public string UserPwd { get; set; } public string Sex { get; set; } public string Phone { get; set; } public string Email { get; set; } public string QQ { get; set; } public string Address { get; set; } public string Remark { get; set; } public bool Disable { get; set; } public virtual ICollection<WMS_OrgUser> UserOrgIds { get; set; } }
页面DTO定义如下:
public class UserDto { public UserDto() { } public Guid Id { get; set; } public string UserName { get; set; } public string NickName { get; set; } public string UserPwd { get; set; } //强制字段映射 [AutoMapping(EntityColumn="Sex")] public string XingBie { get; set; } public string Phone { get; set; } public string Email { get; set; } public string QQ { get; set; } public string Address { get; set; } public string Remark { get; set; } public bool Disable { get; set; } //忽略字段映射 [AutoMapping(Ignore=true)] public DateTime CreateTime { get; set; } }
使用AutoMapper,做转换:
[Action] [Description("更新用户")] [HttpPut] public JsonResult Update(UserDto user) { WMS_User userEntity = WMFactory.WMSUser.GetById(user.Id.ToString()); //*******看这里哦******** userEntity = AutoMapper<UserDto, WMS_User>.Convert(user, userEntity); if (WMFactory.WMSUser.Update(userEntity)) return Json(ResultMsg.Success("用户信息更新成功!")); else return Json(ResultMsg.Failure("用户信息更新失败,请您重试!")); }
写在后面
自己实现,相对来说,自由度高了很多,你可以自己扩展方法,实现客制化的DTO转Entity,让AutoMapper更加适合自己的项目。