【问题标题】:Dynamically get the result of a Func<T,bool> invocation动态获取 Func<T,bool> 调用的结果
【发布时间】:2009-09-14 04:04:39
【问题描述】:

我正在尝试根据满足特定条件对某些内容进行序列化。

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

但是,由于无法做到这一点,我已经决定在类中有一个 Func 成员,并通过 property 属性传递此 Func 的类型(或第一个参数类型)和名称。例如:

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

在我的序列化程序中,我需要调用这个 Func

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

我的幼稚做法是这样的:

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。

那么,谁能指出我正确的方向?

【问题讨论】:

    标签: c# generics reflection dynamic lambda


    【解决方案1】:

    你可以这样做,不需要表达式:

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

    【讨论】:

    • 我有一个类型变量,不是实际类型,你不能去 (Predicate)a.GetValue()。你还能采用这种方法吗?
    • 是的,看看我的编辑,要委托的演员表和 DynamicInvoke。
    • 太棒了!谢谢 :-)。现在看起来最简单的解决方案和测试。
    • 感谢您的代码。这真的帮助我解决了我的问题。
    【解决方案2】:

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

    这是我在 MSDN 上找到的:

    表达式)>) type 提供 Compile 方法, 编译由表示的代码 将表达式树转换为可执行文件 代表。这个可执行代码是 相当于可执行代码 如果有 将 lambda 表达式分配给 最初的委托类型。

    Here你可以找到。

    【讨论】:

    • 是的,谢谢,但我需要一个表达式才能编译它。因为它是我无法创建表达式。
    • 啊,但我看到了一个例子,我可以简单地用 Expression> = (lambda) 代替 (Func>>)。我将确保在我的对象类中引用表达式而不是函数。可惜我找不到动态转换两者的方法。
    • 不是 Func 代表吗?为什么要将其转换为 lambda 表达式?
    • 如果有更好的方法来获得评估 Func 的结果,记住它是对象类型,我很想知道。
    【解决方案3】:

    不确定这是工作示例,但方法如下:

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

    【讨论】:

    • 嗯,它看起来可能会起作用,但请记住,我不知道 SomeObject,我只有一个代表它的类型变量。所以我不能在最后一行去 Expression.Lambda>。但非泛型 Lambda 方法或许能帮到我。
    • 我还试图避免创建包装 Func 的完整方法,因为最初的问题是尽可能轻松地装饰现有属性。
    猜你喜欢
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多