Mapper 实体转换Entiy to Dto

实际使用中发现很多问题 如果用EFcore 框架,这个表达式树生成一个新的实体
导致EFcore 跟踪失败!

/// <summary> /// 生成表达式目录树 泛型缓存 /// </summary> /// <typeparam name="TIn"></typeparam> /// <typeparam name="TOut"></typeparam> public class ExpressionGenericMapper<TIn, TOut>//Mapper`2 { private static Func<TIn, TOut> _FUNC = null; private static Func<TIn, TOut, TOut> _FUNC2 = null; public static TOut Trans(TIn t) { return _FUNC(t); } /// <summary> /// 批量实体转换 /// </summary> /// <param name="list">被转换的实体List</param> /// <returns></returns> public static List<TOut> TransList(List<TIn> list) { List<TOut> outs = new List<TOut>(); foreach (var item in list) { outs.Add(Trans(item)); } return outs; } /// <summary> /// 把TOut 按照TIn来更新 /// </summary> /// <param name="news"></param> /// <param name="old"></param> /// <returns></returns> public static TOut Modify(TIn news, TOut old) { return _FUNC2(news, old); } static ExpressionGenericMapper() { Type stringType = typeof(string); #region 创建构造对象的委托 { ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "m"); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach (var item in typeof(TOut).GetProperties()) { var type = typeof(TIn); if (item.PropertyType.IsClass && item.PropertyType != stringType)//排除String以外的引用类型,不进行赋值 { continue; } var prop = type.GetProperty(item.GetMappingName());//从Out类找映射的字段名 if (prop != null)//如果TIn里能找到该属性 { MemberExpression property = Expression.Property(parameterExpression, prop); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } } foreach (var item in typeof(TOut).GetFields()) { var type = typeof(TIn); if (item.FieldType.IsClass && item.FieldType != stringType)//排除String以外的引用类型,不进行赋值 { continue; } var prop = type.GetField(item.GetMappingName());//从Out类找映射的字段名 if (prop != null) { MemberExpression property = Expression.Field(parameterExpression, prop); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray()); Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression }); _FUNC = lambda.Compile();//拼装是一次性的 } #endregion #region 修改对象的委托 { ParameterExpression oExpression = Expression.Parameter(typeof(TOut), "o"); ParameterExpression nExpression = Expression.Parameter(typeof(TIn), "n"); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach (var item in typeof(TOut).GetProperties()) { var type = typeof(TIn); if (item.PropertyType.IsClass && item.PropertyType != stringType)//排除String以外的引用类型,不进行赋值 { continue; } var prop = type.GetProperty(item.GetMappingName()); if (prop != null) { MemberExpression property = Expression.Property(nExpression, prop); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } else { var propOld = typeof(TOut).GetProperty(item.Name); MemberExpression property = Expression.Property(oExpression, propOld); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } } foreach (var item in typeof(TOut).GetFields()) { var type = typeof(TIn); if (item.FieldType.IsClass && item.FieldType != stringType)//排除String以外的引用类型,不进行赋值 { continue; } var prop = type.GetField(item.GetMappingName()); if (prop != null) { MemberExpression property = Expression.Field(nExpression, prop); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } else { var propOld = typeof(TOut).GetField(item.Name); MemberExpression property = Expression.Field(oExpression, propOld); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray()); Expression<Func<TIn, TOut, TOut>> lambda = Expression.Lambda<Func<TIn, TOut, TOut>>(memberInitExpression, new ParameterExpression[] { nExpression, oExpression }); _FUNC2 = lambda.Compile();//拼装是一次性的 } #endregion } } public static class ExpressionGenericMapperExtend { public static string GetMappingName(this PropertyInfo prop) { if (prop.IsDefined(typeof(MappingAttribute), true)) { MappingAttribute display = prop.GetCustomAttribute(typeof(MappingAttribute)) as MappingAttribute; return display.MappingName; } return prop.Name; } public static string GetMappingName(this FieldInfo prop) { if (prop.IsDefined(typeof(MappingAttribute), true)) { MappingAttribute display = prop.GetCustomAttribute(typeof(MappingAttribute)) as MappingAttribute; return display.MappingName; } return prop.Name; } } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class MappingAttribute : Attribute { public string MappingName; public MappingAttribute(string _MappingName) { this.MappingName = _MappingName; } }

 

posted @ 2022-08-08 11:26  Bo-Hong  阅读(451)  评论(0编辑  收藏  举报