C#进阶系列——动态Lamada(二:优化)

前言:前几天写了一篇动态Lamada的文章C#进阶系列——动态Lamada,受园友xiao99的启发,今天打算来重新优化下这个动态Lamada的工具类。在此做个笔记,以免以后忘了。

一、原理分析

上篇里面我们说了动态Lamada的使用必要性以及使用场景,但是感觉用在项目里面还不太方便,最难用的就是需要传递属性名称的字符串,感觉这有点太lower了。然后就是那个枚举的使用着实感觉没啥必要,我们只需要将Contains、Equal、LessThan、GreaterThan等方法分别封装一个独立的方法即可。好了,多说容易让人头晕,直接上代码吧。

二、代码示例

  public class LamadaExtention<Dto> where Dto:new ()
    {
        private List<Expression> m_lstExpression = null;
        private ParameterExpression m_Parameter = null;

        public LamadaExtention()
        {
            m_lstExpression = new List<Expression>();
            m_Parameter = Expression.Parameter(typeof(Dto), "x");
        }

     //只读属性,返回生成的Lamada
public Expression<Func<Dto, bool>> Lamada {
        
get { return GetLambda(); } } /// <summary> /// 字符串Contains筛选 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void Contains(Expression<Func<Dto, string>> expProperty, object strValue) { Expression expRes = Expression.Call(expProperty.Body, typeof(string).GetMethod("Contains"), Expression.Constant(strValue)); m_lstExpression.Add(expRes); } /// <summary> /// 等于 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void Equal(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.Equal(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 小于 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void LessThan(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.LessThan(member, Expression.Constant( strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 小于等于 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void LessThanOrEqual(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.LessThanOrEqual(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 大于 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void GreaterThan(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.GreaterThan(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 大于等于 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void GreaterThanOrEqual(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.GreaterThanOrEqual(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); }private Expression<Func<Dto, bool>> GetLambda() { Expression whereExpr = null; foreach (var expr in this.m_lstExpression) { if (whereExpr == null) whereExpr = expr; else whereExpr = Expression.And(whereExpr, expr); } if (whereExpr == null) return null; return Expression.Lambda<Func<Dto, Boolean>>(whereExpr, m_Parameter); } //得到MemberExpression private MemberExpression GetMemberExpression(Expression<Func<Dto, object>> exp) { var arrSplit = exp.Body.ToString().Split("(.)".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var strProperty = arrSplit[arrSplit.Length - 1]; MemberExpression member = Expression.PropertyOrField(m_Parameter, strProperty); return member; } }

可以看出,对于常用的操作我们封装了Contains、Equal、LessThan、LessThanOrEqual、GreaterThan、GreaterThanOrEqual六个方法,除了Contains方法的参数直接使用了Expression<Func<DTO, string>>类型以为,其他都用的Expression<Func<DTO, object>>。因为Contains方法只可能是string类型的变量操作,而其他操作可能涉及其他类型,就是为了传这个object类型,有个问题博主调试了很久,由于传过来的是object,这个要得到属性的真是类型貌似不那么容易了,找了很久都没找到。最后只能通过GetMemberExpression这个方法来得到MemberExpression。

还是来看看如何使用:

     public object GetUsers(int limit, int offset, string username, string fullname)
        {
            var oLamadaExtention = new LamadaExtention<DTO_TR_SYS_USERS>();
            oLamadaExtention.Equal(x => x.USER_NAME, username);
            oLamadaExtention.LessThan(x => x.MODIFYTIME, DateTime.Now);
        var lstRes = UserManager.Find(oLamadaExtention.lamada).ToList();
     }

最大的方便就是我们想要筛选的字段可以通过lamada点出来了,再看看之前的那种用法

oLamadaExtention.GetExpression("USER_NAME", username, ExpressionType.Contains);

有没有瞬间高大上。USER_NAME直接点出来,比敲字符串要爽吧。感谢神奇的Lamada,感谢全能的C#,感谢热心的园友。

 

posted @ 2015-11-09 16:35  懒得安分  阅读(3528)  评论(12编辑  收藏  举报