动态select表达式(EF+Dto)

     最近在研究动态拼接Select表达式和Where表达式,发现MemberInitExpression 可以达到我的目的,最初实现了单层的表达式生成,很是开心,然而,问题出现了,对于有导航属性的类型,网上找了一圈,没有解决方案,肿么办???终于在梦中想到一个方案,MemberInitExpression 生成的表达式也可以进行bind的啊,试了一下,果真如此,搞定收工!直接上代码,如下:



public class SelectExpressionBase

    {
        /// <summary>
        /// 生成查询表达式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="parmExpression"></param>
        /// <param name="fieldList">所需查询的列的集合,包含导航属性的全名</param>
        /// <returns></returns>
        public static MemberInitExpression CreateMemberInitExpression<TSource, TDto>(ParameterExpression parmExpression, List<string> fieldList)
        {
            //排序
            fieldList.Sort();


            //对应关系的集合,用于最终生成表达式
            List<MemberBinding> memberBinding = new List<MemberBinding>();
            //获取对应关系的绑定集合
            memberBinding = GetMemberBindingList<TSource, TDto>(parmExpression, fieldList, 0);
            //生成一个new表达式,例如 new Task()
            NewExpression newExpression = Expression.New(typeof(TDto));
            //讲new表达式与对应关系进行合并
            MemberInitExpression memberInitExpression = Expression.MemberInit(newExpression, memberBinding);
            //返回最终select表达式
            return memberInitExpression;
        }


        /// <summary>
        /// 获取绑定表达式集合
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="parmExpression"></param>
        /// <param name="fieldList"></param>
        /// <param name="index">生成表达式为第几级导航属性,初始为0</param>
        /// <returns></returns>
        public static List<MemberBinding> GetMemberBindingList<TSource, TDto>(ParameterExpression parmExpression, List<string> fieldList, int index)
        {
            List<MemberBinding> memberBinding = new List<MemberBinding>();
            //表示存储已经生成的列,再次递归时不再生成该列的表达式
            List<string> tempField = new List<string>();


            foreach (var field in fieldList)
            {
                int len = field.Split('.').Length;
                if (len - 1 == index)
                {
                    //生成当前导航属性级别的基本属性
                    memberBinding.Add(GetMemberBinding<TSource, TDto>(parmExpression, field));
                }
                else
                {
                    //生成当前导航属性级别的子级属性
                    if (string.IsNullOrEmpty(tempField.Where(x => x == field).FirstOrDefault()))//判断该属性是否已生成
                    {
                        string[] nameStr = field.Split('.');
                        //当前导航属性级别的全名
                        string fieldStr = "";
                        for (int i = 0; i < nameStr.Length; i++)
                        {
                            if (i < index)
                            {
                                fieldStr += nameStr[i] + ".";
                            }
                            else if (i == index)
                            {
                                fieldStr += nameStr[i];
                            }
                        }
                        //需要生成表达式的属性集合
                        List<string> currentList = fieldList.Where(x => x.Contains('.') && x.StartsWith(fieldStr + ".")).ToList();
                        //获取所有子级表达式
                        memberBinding.Add(GetChildMemberBinding<TSource, TDto>(parmExpression, currentList, fieldStr, index));
                        currentList.ForEach(x => tempField.Add(x));
                    }
                }
            }


            return memberBinding;
        }


        /// <summary>
        /// 获取子级绑定表达式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="parmExpression"></param>
        /// <param name="fieldList">所有子级属性集合</param>
        /// <param name="childProperty">当前导航属性名称</param>
        /// <param name="index">当前导航属性级别</param>
        /// <returns></returns>
        public static MemberBinding GetChildMemberBinding<TSource, TDto>(ParameterExpression parmExpression, List<string> fieldList, string childProperty, int index)
        {
            //获取属性信息,目的为生成new表达式
            PropertyInfo dtoProperty = GetPropertyInfo<TDto>(null, childProperty);
            Type type = dtoProperty.PropertyType;
            NewExpression newExpression = Expression.New(type);
            //导航属性的对象表达式,用于生成导航属性对象,例如:Task = new P_Task()........(其中前面的Task)
            NewExpression dtoNewExpression = Expression.New(typeof(TDto));
            MemberInfo dtoMember = GetMemberExpression<TDto>(null, dtoNewExpression, childProperty).Member;
            //递归调用,获取子级绑定表达式,最终生成例如:Task = new P_Task()........
            MemberBinding memberBinding = System.Linq.Expressions.Expression.Bind(dtoMember,
                Expression.MemberInit(newExpression, GetMemberBindingList<TSource, TDto>(parmExpression, fieldList, index + 1)));
            return memberBinding;
        }


        /// <summary>
        /// 获取绑定表达式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="parmExpression"></param>
        /// <param name="propertyName">属性全名,包含导航属性</param>
        /// <returns></returns>
        public static MemberBinding GetMemberBinding<TSource, TDto>(ParameterExpression parmExpression, string propertyName)
        {
            //new表达式
            NewExpression newExpression = Expression.New(typeof(TDto));
            //EF属性表达式
            Expression memExpression = GetPropertyExpression<TSource>(null, parmExpression, propertyName);
            //Dto属性表达式
            MemberInfo dtoMembers = GetMemberExpression<TDto>(null, newExpression, propertyName).Member;
            //绑定
            MemberBinding memberBinding = System.Linq.Expressions.Expression.Bind(dtoMembers, memExpression);
            return memberBinding;
        }


        /// <summary>
        /// 获取导航属性表达式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="para"></param>
        /// <param name="fullName"></param>
        /// <returns>最终生成类似x.A.B.C格式的表达式</returns>
        public static Expression GetPropertyExpression<TSource>(Expression source, ParameterExpression para, string fullName)
        {
            string[] propertys = fullName.Split('.');
            if (source == null)
            {
                source = Expression.Property(para, typeof(TSource).GetProperty(propertys.First()));
            }
            else
            {
                source = Expression.Property(source, propertys.First());
            }
            foreach (var item in propertys.Skip(1))
            {
                source = GetPropertyExpression<TSource>(source, para, item);
            }
            return source;
        }


        /// <summary>
        /// 通过导航属性获取最后一级的属性信息
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static PropertyInfo GetPropertyInfo<TSource>(PropertyInfo source, string fullName)
        {
            string[] propertys = fullName.Split('.');
            if (source == null)
            {
                source = typeof(TSource).GetProperty(propertys.First());
            }
            else
            {
                source = source.PropertyType.GetProperty(propertys.First());
            }
            foreach (var item in propertys.Skip(1))
            {
                source = GetPropertyInfo<TSource>(source, item);
            }
            return source;
        }


        /// <summary>
        /// 获取目标成员表达式
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="newExpression"></param>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static MemberExpression GetMemberExpression<TSource>(MemberExpression source, Expression newExpression, string fullName)
        {
            string[] propertys = fullName.Split('.');
            if (source == null)
            {
                source = MemberExpression.MakeMemberAccess(newExpression, typeof(TSource).GetMember(propertys.First())[0]);
            }
            else
            {
                source = MemberExpression.MakeMemberAccess(source, Expression.Property(source, propertys.First()).Member);
            }
            foreach (var item in propertys.Skip(1))
            {
                source = GetMemberExpression<TSource>(source, source, item);
            }
            return source;
        }


    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值