gpt4 book ai didi

c# - 指定参数取泛型方法表达式

转载 作者:太空狗 更新时间:2023-10-29 21:57:35 24 4
gpt4 key购买 nike

我想指定一个可以接受方法的参数,而不必指定通用参数来生成给定方法的 MethodInfo。

例如,我想写这样的代码:

interface IService
{
object AMethod(int p1, int p2);
}
IThingy<IService>() thingy;
thingy.Add(svc => svc.AMethod);

我能给出的最接近的选项是:

interface IThingy<TService>
{
void Add1<T0, T1, TResult>(Expression<Func<TService, Func<T0, T1, TResult>>> expression);
void Add2(Expression<Func<TService, Func<int, int, object>>> expression);
void Add3(Expression<Action<TService>> expression);
}
thingy.Add1<int, int, object>(svc => svc.AMethod);
thingy.Add2(svc => svc.AMethod);
thingy.Add3(svc => svc.AMethod(0, 0));

Add1 意味着许多 Func 重载,我同意,但不能在不指定通用参数的情况下调用。

Add2 不需要通用参数,但暗示每个参数签名的特定重载。

Add3 需要调用该方法,包括假参数。

仅供引用,我将处理表达式以获取给定方法的 MethodInfo,如下所示:

MemberInfo GetMemberFromExpression<T>(Expression<ActionT>> expression)
{
return ((MethodCallExpression)expression.Body).Method
}
GetMemberFromExpression(svc => svc.AMethod(0, 0));

最佳答案

将方法传递给具有调用值的表达式

您可以按原样使用 GetMemberFromExpression 方法,然后只需删除 Generic 参数即可。如下:

static void Main(string[] args)
{
var memberInfo1 = GetMemberFromExpression(() => Method1(10, 20));
var memberInfo2 = GetMemberFromExpression(() => Method2());
var memberInfo3 = GetMemberFromExpression(() => Method3("string", 15, DateTime.Now));
Console.WriteLine(memberInfo1.Name);
Console.WriteLine(memberInfo2.Name);
Console.WriteLine(memberInfo3.Name);
Console.Read();
}

public static MemberInfo GetMemberFromExpression(Expression<Action> expression)
{
return ((MethodCallExpression)expression.Body).Method;
}

public static object Method1(int p1, int p2)
{
return p1 + p2;
}

public static void Method2()
{
// No return
}

public static double Method3(string p1, int p2, DateTime p3)
{
return 10d;
}

您会看到 GetMemberFromExpression 将返回您传递给它的任何方法的 MethodInfo,无论参数类型和返回类型如何。


忽略重载,调用实例和名称

如果您不关心重载,您可以使用简单的反射而不是构建表达式。 C# 6 中的 nameof 运算符是一种比将名称作为字符串传递(编译时检查)更好的方法。

public static MemberInfo GetMemberInfo(Type type, string methodName)
{
return type.GetMethod(methodName);
}

请注意,此方法中没有验证检查,只是为了展示概念。

上述方法适用于任何实例或静态方法。只需传递实例类型/或静态类类型和方法名,如下所示:

MyClass cl = new MyClass();
var methodInfo1 = GetMemberInfo(cl.GetType(), "AMethod");
var methodInfo2 = GetMemberInfo(typeof(MyClass), "AStaticMethod");

这是 MyClass 的方法:

class MyClass
{
public void AMethod(int a, int b)
{
// instance method
}

public static bool AStaticMethod(bool a, bool b)
{
return a & b; // static method
}
}

这样您就不会传递任何参数,因为您只是在调查定义而不是调用。


使用带有类型而不是值的表达式

这是第三种选择。这样你就有了:

  • 编译时检查,
  • 无需传递有值(value)的(“假的”)参数,
  • 只有所需的参数类型(这确保重载方法将起作用)。

ActionFunc 重载创建一个类:

public class Method
{
public static MethodInfo GetInfo<TReturn>(Func<TReturn> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TReturn>(Func<TP1, TReturn> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TP2, TReturn>(Func<TP1, TP2, TReturn> method)
{
return method.Method;
}
//... Continue with some more Func overloads


public static MethodInfo GetInfo(Action method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1>(Action<TP1> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TP2>(Action<TP1, TP2> method)
{
return method.Method;
}
//... Continue with some more Action overloads
}

现在您可以按如下方式简单地获取MethodInfo:

var methodInfo1 = Method.GetInfo<int, int>(cl.AMethod);
var methodInfo2 = Method.GetInfo<bool, bool, bool>(MyClass.AStaticMethod);

是的,您必须在 Method 类中为 ActionFunc 创建一堆重载,但这是一次性的事情你会这样做,.NET 也会对 ActionFunc 委托(delegate)做同样的事情,以满足所有重载。

关于c# - 指定参数取泛型方法表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28228977/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com