FreeSql - 扩展InsertInto方法,自动补全表达式树中相同属性的初始化操作

封装了一个语法糖

        /// <summary>
        /// InsertInto基础上,自动补全表达式树中相同属性的初始化操作
        /// <para>
        /// 补全效果:x => new Person {Name = x.Name, Age = x.Age, ...}
        /// </para>
        /// <para>
        /// ※ 若需自动完成所有相同属性的初始化操作,应写为 x => new Person {},而非 x => new Person()
        /// </para>
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="TTargetEntity"></typeparam>
        /// <param name="selector"></param>
        /// <param name="tableName">指定插入的表名,若为 null 则使用 TTargetEntity 实体表名</param>
        /// <param name="select">选择列</param>
        /// <returns>返回影响的行数</returns>
        public static int InsertIntoDiy<T1, TTargetEntity>(this ISelect<T1> selector, string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class
        {
            return selector.InsertInto(tableName, AutoComplete(select));
        }

        /// <summary>
        /// 生成自动补全相同属性的表达式树
        /// </summary>
        /// <typeparam name="TParam"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        private static Expression<Func<TParam, TResult>> AutoComplete<TParam, TResult>(Expression<Func<TParam, TResult>> exp)
        {
            Expression node = exp.Body;
            if (node.NodeType != ExpressionType.MemberInit) return exp;

            MemberInitExpression initExp = node as MemberInitExpression;
            IEnumerable<string> bindingNames = initExp.Bindings.Select(x => x.Member.Name);
            ParameterExpression param = Expression.Parameter(typeof(TParam), exp.Parameters[0].Name);
            PropertyInfo[] resultProps = typeof(TResult).GetProperties();

            List<MemberBinding> bindings = new();
            bindings.AddRange(initExp.Bindings);

            foreach (PropertyInfo prop in typeof(TParam).GetProperties())
            {
                // 忽略已初始化的属性
                if (bindingNames.Contains(prop.Name)) continue;

                PropertyInfo resultProp = resultProps.FirstOrDefault(x => x.Name == prop.Name);
                // 忽略TResult不存在的属性
                if (resultProp == null) continue;

                KeyAttribute keyAttr = resultProp.GetCustomAttribute<KeyAttribute>();
                // 忽略Key属性
                if (keyAttr != null) continue;

                MemberExpression memberAccess = Expression.MakeMemberAccess(param, prop);
                bindings.Add(Expression.Bind(resultProp, memberAccess));
            }

            MemberInitExpression body = initExp.Update(initExp.NewExpression, bindings);
            return Expression.Lambda<Func<TParam, TResult>>(body, new ParameterExpression[] { param });
        }

原文:https://www.cnblogs.com/tinymad/p/15956283.html

posted @ 2022-03-02 17:45  TinyMaD  阅读(125)  评论(0)    收藏  举报