.NET Lambda 传递方法参数

发布于 2024-09-03 12:12:44 字数 501 浏览 1 评论 0原文

我希望我错过了一些明显的东西,但是我在定义一个方法时遇到了一些麻烦,该方法采用方法的参数来获取传递方法的方法信息。我不想实际执行该方法。

我希望能够做到:

  busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById);

其中 GetNameById 是接口 ISomeInterface 上定义的方法。在这种情况下,传入签名的方法的示例如下:

 MyVarA GetNameById(int id){ .... }

在上面的示例中,SetResolverMethod 的主体应该能够返回/存储字符串“GetNameById”。

传入的方法没有遵循的标准签名(除了它总是返回某种类型的对象)。

目前,我将该方法设置为字符串(即“GetNameById”),但我希望对其进行编译时检查,因此出现了这个问题。

I hope i'm missing something obvious, but I'm having some troubles defining a method that takes a parameter of a method to fetch the method information for the passed method. I do NOT want actually execute the method.

I want to be able to do:

  busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById);

Where GetNameById is a method defined on the interface ISomeInterface. In this case, an example of the method being passed in's signature would be:

 MyVarA GetNameById(int id){ .... }

In the above example, the SetResolverMethod's body should be able to return / store the string "GetNameById".

There is no standard signature the method being passed in will conform to (except that it will always return an object of some kind).

Currently I'm setting the method as a string (i.e. "GetNameById"), but I want it to be compile time checked, hence this question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

停顿的约定 2024-09-10 12:12:44

它不是特别漂亮/流畅,但如果您确实想避免传递虚拟参数值,那么您可以使用返回委托的表达式。

SetResolverMethod<ISomeInterface>(x => new Func<int, MyVarA>(x.GetNameById));

SetResolverMethod 实现如下所示:

public void SetResolverMethod<T>(Expression<Func<T, Delegate>> expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}

编辑:如果您愿意为每个 Func 委托创建一组重载,您可以通过将方法参数类型包含在方法的泛型参数类型中来提高流畅性。

p.SetResolverMethod<ISomeInterface, int, MyVarA>(x => x.GetNameById);

正如您所看到的,调用者不再需要指定委托类型,从而节省了大约 8 个字符。

我已经为 0、1 和 2 参数实现了三个重载:

public void SetResolverMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, TResult>(Expression<Func<T, Func<T1, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, T2, TResult>(Expression<Func<T, Func<T1, T2, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

private void SetResolverMethod(LambdaExpression expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}

It's not particularly pretty/fluent but if you really want to avoid having to pass dummy parameter values then you can use an expression that returns a delegate.

SetResolverMethod<ISomeInterface>(x => new Func<int, MyVarA>(x.GetNameById));

The SetResolverMethod implementation would look something like this:

public void SetResolverMethod<T>(Expression<Func<T, Delegate>> expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}

Edit: If you're willing to create as set of overloads for each Func<> delegate, you can improve the fluency by including the method parameter types in the generic parameter types of your method.

p.SetResolverMethod<ISomeInterface, int, MyVarA>(x => x.GetNameById);

As you can see, the caller no longer needs to specify a delegate type, thus saving around 8 characters.

I've implemented three overloads for 0, 1 and 2 parameters:

public void SetResolverMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, TResult>(Expression<Func<T, Func<T1, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, T2, TResult>(Expression<Func<T, Func<T1, T2, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

private void SetResolverMethod(LambdaExpression expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}
药祭#氼 2024-09-10 12:12:44

没有办法只传递方法本身。您可以通过将方法包装在委托中来完成此操作,但为此,您必须让 SetResolverMethod 方法定义该委托的类型(您不能这样做,因为正如您所说,没有一个签名),或者在调用时显式指定该类型,这将是脏的。

您可以做的是让 SetResolverMethod 接受一个 lambda 表达式,该表达式接受 ISomeInterface 并返回whatever,并传递该方法的实际执行无论参数作为该表达式的主体。就像这样:

    void SetResolverMethod<T>( Expression<Func<T,object>> expr );

    ...

    SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) )

SetResolverMethod 方法不会实际执行表达式,只会分析它 - 因此,您的方法实际上不会被执行。

这是你需要的吗?

There is no way to pass just the method itself. You could do it by wrapping the method in a delegate, but for that, you have to either have the SetResolverMethod method define the type of that delegate (which you can't do, because, as you said, there is no one signature), or explicitly specify that type when calling, which would be dirty.

What you could do instead is have the SetResolverMethod take a lambda expression that takes ISomeInterface and returns whatever, and pass the actual execution of the method with whatever arguments as the body of that expression. Like so:

    void SetResolverMethod<T>( Expression<Func<T,object>> expr );

    ...

    SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) )

The SetResolverMethod method will not actually execute the expression, only analyze it - therefore, your method will not actually be executed.

Is this what you need?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文