在c#中可以将方法参数包装为不带lambda表达式的函数

本文关键字:lambda 表达式 函数 包装 参数 方法 | 更新日期: 2023-09-27 18:02:51

假设我有一个签名如下的方法:

public void MyMethod(Func<int> expression)
{
    // Does work
}

我这样调用这个方法:

int intProperty = 7;
MyMethod(() => intProperty);

是否有某种方法可以在不使用lambda的情况下调用该方法?所以我想让它看起来像这样:

MyMethod(intProperty);

如果方法签名必须改变,这对我来说并不重要-我有点指望这一点。我尝试这样做的原因是,当它作为一个函数传入时,您可以检查关于初始属性的附加信息,我需要能够访问。

我不相信在MyMethod中使用反射会在这里工作,因为我想要原始参数的信息。它们是获取信息的方法,比如从函数中获取它的名称,这是我希望能够检索到的。我已经能够做到这一点了。因此,在上面的例子中,MyMethod将能够告诉传入的属性的名称为intProperty。

注意:这是一个简化的例子。我很清楚,如果我想要的话,我可以直接把房子搬进去。但是我想要关于Func在这里捕获的原始属性的额外信息,比如它的原始名称。

在c#中可以将方法参数包装为不带lambda表达式的函数

不能对属性这样做,但可以对类属性的getter方法这样做。从c# 3.0开始,您可以使用方法组隐式构建委托:

public void MyMethod(Func<int> expression) {
    // Does work
}
public int GetProperty() {
    return 123;
}
pubic void Test() {
    MyMethod(GetProperty /* NO PARENTHESES HERE!!! */);
}

在方法名后去掉括号将调用表达式转换为方法组。不幸的是,这意味着属性没有类似的语法,因为访问属性不需要括号。

使用表达式

您提到方法签名是否必须更改并不重要。那么为什么不将方法签名更改为:

public void MyMethod<T>(T source, Expression<Func<T, int>> expression)
{
    // Evaluate expression
}
MyMethod(this, x => x.property);

我不会在这里讨论解析表达式树的太多细节,但要了解更多信息,请参阅SO中的这个问题:

从lambda表达式中检索属性名

使用反射

您也可以使用反射来获取有关属性的信息。如果您不需要获取该属性的实际值,请删除source参数。

public void MyMethod(object source, string propertyName)
{
    var pi = source.GetType().GetProperty(propertyName);
    if (pi == null)
    {
        throw new Exception("property not found");
    }
    MyMethod(source, pi);
}
public void MyMethod(object source, PropertyInfo property)
{
    // Evaluate property
}
MyMethod(this, "Property");