动态获取Func <t,bool>调用</t,bool>的结果

时间:2009-09-14 04:04:39

标签: c# generics reflection dynamic lambda

我正在尝试根据特定标准序列化某些内容。

为此,我最初的希望是在对象的属性上使用包含lambda表达式的属性。

然而,由于无法做到这一点,我已经决定使用Func&lt; T,bool&gt;类中的成员,并通过property属性传递此Func的类型(或第一个参数类型)和名称。 E.g:

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

在我的序列化程序中,我需要调用此Func&lt; T,bool&gt;。

假设在这种情况下我有一个类型t等于typeof(SomeObject),或者更抽象地,typeof(T)。我也可以得到Func&lt; T,bool&gt;本身,但只能通过反射作为对象。

我天真的做法是这样的:

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 */

但这会导致将lambda转换为委托的问题,这显然是错误的。

我试过这个代替'func':

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

但是依赖于func是一个方法调用而不是lambda。

那么,有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:4)

你可以做这样的事情,而不需要表达式:

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

并获取值:

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

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

编辑以在不知道类型的情况下获取值:

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

答案 1 :(得分:1)

我认为您可以使用lambda表达式的Compile方法将其强制转换为委托。

这是我在MSDN上找到的内容:

  

表达式&lt;(&lt;(TDelegate&gt;)&gt;)   type提供Compile方法,   编译由代表的代码   将表达式树转换为可执行文件   代表。这个可执行代码是   相当于可执行代码   本来会产生的   lambda表达式已分配给a   委托类型最初。

Here你可以找到它。

答案 2 :(得分:1)

不确定这是工作样本,但这是方法:

// 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);

现在您可以像这样调用“func”方法:

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