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#,感謝熱心的園友。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM