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

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com