簡體   English   中英

如何從Lambda表達式中獲取價值?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM