我想指定一个可以接受方法的参数,而不必指定泛型参数来生成给定方法的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));
答案 0 :(得分:1)
您可以使用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
}
}
这样您就不会传递任何参数,因为您只是在调查定义而不是调用。
这是第三种选择。这样你就有了:
创建一个适合Action
和Func
重载的类:
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
类中为Action
和Func
创建一堆重载,但这是你做过的一次性事情,而.NET会做与Action
和Func
代表相同,以满足所有重载。