[英]How to get value from a lambda expression?
我有這個課:
public class CustomerFilter
{
public int Id { get; set; }
public int Name { get; set; }
}
它的用法是這樣的:
public class Search
{
private Expression<Func<CustomerFilter, bool>> customerfilter;
public Expression<Func<CustomerFilter, bool>> CustomerFilter
{
set { customerfilter = value; }
}
}
var search = new Search();
search.CustomerFilter = (x => x.Id == 1);
在搜索類中,如何在不使用ExpressionVisitor
情況下獲取屬性的值? 就像是:
var customerId = customerFilter.Id; //Or something similar
不太了解您為什么需要它。 但是,您可以執行以下操作:
public class Search
{
private Expression<Func<CustomerFilter, bool>> customerfilter;
public Expression<Func<CustomerFilter, bool>> CustomerFilter
{
set { customerfilter = value; }
}
public object GetValue(CustomerFilter filter)
{
var property = (customerfilter.Body as BinaryExpression).Left;
var lambda =Expression.Lambda(property, customerfilter.Parameters.First());
return lambda.Compile().DynamicInvoke(filter);
}
}
使用這種用法:
var search = new Search();
search.CustomerFilter = (x => x.Id == 1);
var filter = new CustomerFilter {Id = 12};
search.GetValue(filter).Dump();
我得到12
作為輸出
如果您的CustomerFilter
僅像示例代碼中那樣支持MemberExpression==ConstantExpression
。 然后,您可以直接從Expression
對象獲取信息。
var propertyName = ((MemberExpression)((BinaryExpression)customerfilter.Body).Left).Member.Name;
var propertyValue = ((ConstantExpression)((BinaryExpression)customerfilter.Body).Right).Value;
如果要支持更復雜的表達式,則應使用ExpressionVisitor
來解析expression
樹。
擁有一個類和一個屬性CustomerFilter
代表了截然不同的東西,這有點令人誤解。 據我了解,該類最好命名為Customer
:
public class Customer
{
public int Id { get; set; }
public int Name { get; set; }
}
public class Search
{
private Expression<Func<Customer, bool>> customerfilter;
public Expression<Func<Customer, bool>> CustomerFilter
{
set { customerfilter = value; }
}
}
var search = new Search();
search.CustomerFilter = (x => x.Id == 1);
那么很明顯,您的Search
類中沒有屬性customerFilter.Id
。 您只有一個可以接受任何(!) Customer
並將其轉換為bool
的表達式。 通過將Customer.Id
與給定值進行比較來做到這一點,但是Search
對此並不了解。
如果您需要在Search
獲取比較ID,建議您將CustomerFilter
屬性的類型更改為具有公共ComparisonId
屬性的類,並根據該ID生成過濾器表達式:
class CustomerIdFilter // note: this will not replace your existing CustomerFilter which I have renamed to Customer
{
public CustomerIdFilter(int id){ ComparisonId = id; }
public int ComparisonId{ get; private set}
// To filter use this
public bool IsValid(Customer c){ return c.Id == ComparisonId; }
// or maybe something similar to this, if necessary
public Expression<Func<Customer, bool>>FilterExpression
{
get
{
return (x=>x.Id == ComparisonId);
}
}
}
您的代碼將更改為s.th。 然后這樣:
public class Search
{
private CustomerIdFilter customerfilter;
public CustomerIdFilter CustomerFilter
{
set { customerfilter = value; }
}
}
var search = new Search();
search.CustomerFilter = new CustomerIdFilter(1);
根據xwlantian的答案,我進一步進行了以下操作,它適用於簡單的表達式:
var value = Expression.Lambda(((BinaryExpression)customerFilter.Body).Right).Compile().DynamicInvoke();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.