Dynamically get the result of calling Func <T, bool>

I am trying to serialize something based on certain criteria.

To this end, my initial hope was to use attributes containing a lambda expression for the object's properties.

However, since this cannot be done, I decided that the class had a Func <T, bool> member and passed the type (or the first parameter type) and the name of this Func via a property attribute. For example:.

Func<SomeObject, bool> func = (p => p.Value == 4);
[FuncAtt(typeof(SomeObject), "func")]
public SomeObject PropertyName { get; set;}

      

In my serializer, I need to call this Func <t, bool>.

Suppose I have a type t, which in this case would be typeof (SomeObject), or more abstractly, typeof (T). I can also get the Func <T, bool> itself, but only through reflection as an object.

My naive approach is something like this:

object func = typeof(MyClass).GetField(attribute.FuncName).GetValue(MyClassInstance);
Type funcType = typeof(Func<,>).MakeGenericType(attribute.Type, typeof(bool));

ParameterExpression p = Expression.Parameter(attribute.Type, objectToSerialize);
LambdaExpression l = Expression.Lambda(funcType, func, p); /* Won't work */

      

But this leads to the problem of casting the lambda for the delegate, which seems to be wrong.

I tried this instead of "func":

(Expression)((Action)(() => func))

      

But that depends on func being a method call and not a lambda.

So, can anyone point me in the right direction?

+2


source to share


3 answers


You can simply do something like this, without the need for an expression:

public static class Test
{
    public static Predicate<int> func = s => s > 20;
}

      

and get the value:



    private void Form1_Load(object sender, EventArgs e)
    {
        var a = typeof(Test).GetField("func");

        bool validates = ((Predicate<int>)a.GetValue(null)).Invoke(100);
    }

      

modify to get the value without knowing the type:

bool validates = (bool)((Delegate)a.GetValue(null)).DynamicInvoke(100);

      

+4


source


I think you can use the lambda expression compile method to pass it to the delegate.

here is what I found on MSDN:



The expression <(Of <(TDelegate>)>) type provides a compilation method that compiles the code represented by the expression tree into an executable to delegate. This executable code is the equivalent of the executable code that would be generated if the lambda expression were assigned a delegate type.

Here you can find it.

+1


source


Not sure if this is a working sample, but this is the way:

// not sure what are you doing in this line, but assume it should return
// a method name specified in the attribute, e.g. "func" in your example.
// Also "func" must be a method (static one in my example) of SomeObject class
String funcname = typeof(MyClass).GetField(attribute.FuncName).GetValue(MyClassInstance);
ParameterExpression param = Expression.Parameter(typeof(SomeObject), "p");
MethodCallExpression call = Expression.Call(SomeObject, funcname, new Type[] { typeof(SomeObject), typeof(Boolean) }, param);
LambdaExpression lambda = Expression.Lambda<Func<SomeObject, Boolean>>(call, param);

      

now you can call the "func" method like this:

Boolean result = lambda.Compile()(SomeObjectInstance);

      

+1


source







All Articles