[英]How to get lambda expression parameters
在我的特定情況下,我動態地構建一個SQL語句來搜索記錄。 這發生在WebApi的服務器端,位於業務服務層。 現在,我想擴展此功能,以便也可以在客戶端設置WHERE
子句。 我想使用強類型,以便不對客戶端上的列名稱進行硬編碼。
到目前為止,我執行了以下操作:
1)從INFORMATION_SCHEMA
獲取視圖的列,並填充Dictionary<string, object>
以便在稍后階段設置列值。 我可能會更改為自定義類,以便可以添加比較器字段,而不是只有column_name = column_value
。
2)我創建了一個自定義屬性和一個僅包含要向客戶端公開的搜索列的類:
public class CustomerSearchDto
{
[SearchColumn(Name = "customer_type")]
public CustomerType CustomerType { get; set; }
[SearchColumn(Name = "city")]
public string City { get; set; }
public CustomerSearchDto()
{ }
}
3)現在,在客戶端中,我可以執行以下操作:
//Following line is pseudo-code
var predicate = (x => x.CustomerType == CustomerType.Private);
如何獲取此lambda表達式,並從(1)中獲得列列表,並從(2)中獲知列名稱,設置字典中相應列的值?
有太多的假設,但是您可以從以下內容開始:
static void SetValue<T>(Dictionary<string, object> target, Expression<Func<T, bool>> predicate)
{
var comparison = predicate.Body as BinaryExpression;
Debug.Assert(comparison != null);
var member = (comparison.Left.NodeType == ExpressionType.Convert ?
((UnaryExpression)comparison.Left).Operand :
comparison.Left) as MemberExpression;
Debug.Assert(member != null);
var value = comparison.Right as ConstantExpression;
Debug.Assert(value != null);
var attribute = Attribute.GetCustomAttribute(member.Member, typeof(SearchColumnAttribute)) as SearchColumnAttribute;
var columnName = attribute?.Name ?? member.Member.Name;
var columnValue = value.Value;
target[columnName] = columnValue;
}
測試:
Expression<Func<CustomerSearchDto, bool>> predicate = (x => x.CustomerType == CustomerType.Private);
var dict = new Dictionary<string, object>();
SetValue(dict, predicate);
您可以通過使用ExpressionVisitor
重寫客戶端,從而一步一步地將客戶端表達式從SQL表達式轉換為SQL表達式,而不是構建字典然后從中進行查詢。
您的ExpressionVisitor
將覆蓋適當的方法,例如, protected override Expression VisitMember(MemberExpression node)
,在該方法內部,它將客戶端字段名稱轉換為服務器端字段名稱。
仍然存在序列化Expressions客戶端並在服務器端反序列化它們的問題,但是一旦有了它們,就可以使用訪問者為SQL重寫它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.