Func<> getting the parameter info
Asked Answered
L

4

9

How to get the value of the passed parameter of the Func<> Lambda in C#

IEnumerable<AccountSummary> _data = await accountRepo.GetAsync();
string _query = "1011";
Accounts = _data.Filter(p => p.AccountNumber == _query);

and this is my extension method

public static ObservableCollection<T> Filter<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
{
        string _target = predicate.Target.ToString();
        // i want to get the value of query here.. , i expect "1011"

        throw new NotImplementedException();
}

I want to get the value of query inside the Filter extension method assigned to _target

Limen answered 17/7, 2013 at 6:28 Comment(2)
You will have to use Expression<Func<T,bool>> to get that info.Volatilize
ok.. im trying but i cant figure out where to get it.. maybe somewhere in predicate.Body....RightLimen
P
14

If you want to get the parameter you will have to pass expression. By passing a "Func" you will pass the compiled lambda, so you cannot access the expression tree any more.

public static class FilterStatic
{
    // passing expression, accessing value
    public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, Expression<Func<T, bool>> predicate)
    {
        var binExpr = predicate.Body as BinaryExpression;
        var value = binExpr.Right;

        var func = predicate.Compile();
        return collection.Where(func);
    }

    // passing Func
    public static IEnumerable<T> Filter2<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
    {
        return collection.Where(predicate);
    }
}

Testmethod

var accountList = new List<Account>
{
    new Account { Name = "Acc1" },
    new Account { Name = "Acc2" },
    new Account { Name = "Acc3" },
};
var result = accountList.Filter(p => p.Name == "Acc2");  // passing expression
var result2 = accountList.Filter2(p => p.Name == "Acc2");  // passing function
Pawpaw answered 17/7, 2013 at 7:32 Comment(0)
S
1

so instead of passing your predicate as a Func<T,bool> pass an Expression tree instead Expression<Func<T,bool>

You can then examine what type of expression it is and get it's component parts, it won't affect how the method is called, you can still pass it a lambda.

Swarey answered 17/7, 2013 at 6:38 Comment(3)
i made it up to this.. var _a = predicate; var _aa = _a.Body as System.Linq.Expressions.BinaryExpression; var _r = _aa.Right; now i want to get the value of _rLimen
yep, thats the idea...but you will need to check the expression type, as it might not be a binary expression, could be a method call, or a constant etcSwarey
_r will be an expression as well, if its a constant, then you are sweet, but of course it might also be a method call, you just need to keep traversing the tree (generally you would use a visitor to do this)Swarey
S
0

I don't really think you can do that. Check following situation:

Your predicate is set to be Func<T, bool> predicate, so you can call it like that:

Accounts = _data.Filter(p => true);

What would you like to get from that kind of call?

(p) => true satisfies Func<T, bool>, because it takes T as input and returns bool value.

Scanty answered 17/7, 2013 at 6:31 Comment(1)
i want to get the value of _query so i can check if it contains a value or not..Limen
R
0

I was inspired by Fried's answer, and found another approach to solve this:

  1. Wrap the Func<T, bool> inside an Expression

  2. Convert Expression.Right into Lambda function Func that will return the RHS value of the expression.

     public static void Filter<T>(this IEnumerable<T> collection, Expression<Func<T, bool>> predicate)
     {
        int value = Expression.Lambda<Func<int>>(predicate.Right).Compile().Invoke();
     }
    
Romy answered 17/4, 2021 at 15:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.