簡體   English   中英

修改表達 <Func<T, bool> &gt;

[英]Modifying Expression<Func<T, bool>>

我沒有使用過太多的表達式,所以我無法說出我的意圖是否有意義。 我環顧了整個網絡,因此毫無用處。

說我有這樣的方法

public async Task<T> GetFirstWhereAsync(Expression<Func<T, bool>> expression)
{
    // this would be a call to 3rd party dependency
    return await SomeDataProvider
        .Connection
        .Table<T>()
        .Where(expression)
        .FirstOrDefaultAsync();
}

從我的其他代碼中,我可以稱其為

private async Task<User> GetUser(Credentials credentials)
{
    return await SomeDataSource
        .GetFirstWhereAsync(u => u.UserName.Equals(credentials.UserName));
}

因此,我SomeDataProvider與給定表達式匹配的SomeDataProvider中接收第一個User


我的實際問題是,我將如何修改GetFirstWhereAsync以便將一些SecretSauce應用於傳遞給它的任何表達式? 我可以在呼叫者中執行此操作,但這將很丑陋,並且不會帶來很多樂趣。

因此,如果我傳遞類似

u => u.UserName.Equals(credentials.UserName);
p => p.productId == 1;

我希望這些可以修改為

u => u.UserName.Equals(SecretSauce.Apply(credentials.UserName));
p => p.productId == SecrectSauce.Apply(1);

您可以在方法內部修改表達式,但這有點復雜,您需要根據具體情況進行修改。

下面的示例將處理從x => x.Id == 1x => x.Id == SecretSauce.Apply(1)


class User
{
    public int Id { get; set; }
    public string Name { get; set;}

    public override string ToString()
    {
        return $"{Id}: {Name}"; 
    }
}

class SquareSauce
{
    public static int Apply(int input)
    {
        // square the number
        return input * input;
    }
}

數據

User[] user = new[]
{
    new User{Id = 1, Name = "One"},
    new User{Id = 4, Name = "Four"},
    new User{Id = 9, Name = "Nine"}
};

方法

User GetFirstWhere(Expression<Func<User, bool>> predicate)
{
    //get expression body
    var body = predicate.Body;

    //get if body is logical binary (a == b)
    if (body.NodeType == ExpressionType.Equal)
    {
        var b2 = ((BinaryExpression)body);
        var rightOp = b2.Right;

        // Sauce you want to apply
        var methInfo = typeof(SquareSauce).GetMethod("Apply");      

        // Apply sauce to the right operand
        var sauceExpr = Expression.Call(methInfo, rightOp);

        // reconstruct equals expression with right operand replaced 
        // with "sauced" one
        body = Expression.Equal(b2.Left, sauceExpr);

        // reconstruct lambda expression with new body
        predicate = Expression.Lambda<Func<User, bool>>(body, predicate.Parameters);
    }
    /*
        deals with more expression type here using else if
    */
    else
    {
        throw new ArgumentException("predicate invalid");
    }

    return user
        .AsQueryable()
        .Where(predicate)
        .FirstOrDefault();
}

用法

Console.WriteLine(GetFirstWhere(x => x.Id == 2).ToString());

該方法將x => x.Id == 2變為x => x.Id == SquareSauce.Apply(2)並將產生:

4:四

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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