如何使用反射在.NET中调用重载方法

79

在.NET (2.0)中,有没有一种使用反射调用重载方法的方式。我的应用程序动态实例化从一个通用基类派生的类。出于兼容性考虑,这个基类包含了两个同名方法,一个带参数,一个不带参数。我需要通过Invoke方法调用不带参数的方法。目前,我得到的只是一个错误提示,告诉我正在尝试调用一个模棱两可的方法。

是的,我可以将对象强制转换为我的基类的实例,并调用我需要的方法。最终这样做是可以的, 但是现在由于内部复杂性的原因我不能这样做。

任何帮助都将是非常感谢的!谢谢。

3个回答

134

您必须指定您想要的方法:

class SomeType 
{
    void Foo(int size, string bar) { }
    void Foo() { }
}

SomeType obj = new SomeType();
// call with int and string arguments
obj.GetType()
    .GetMethod("Foo", new Type[] { typeof(int), typeof(string) })
    .Invoke(obj, new object[] { 42, "Hello" });
// call without arguments
obj.GetType()
    .GetMethod("Foo", new Type[0])
    .Invoke(obj, new object[0]);

7
你也可以使用 Type.EmptyTypes。 - yoel halb
2
需要在 "typeof(int), typeof(string)" 后面加上 } 才能编译 :) - Omid.Hanjani
2
如果其中一个参数是泛型,会怎么样? - Steven Turner
当您拥有一个对象实例时,您就知道它已被实例化的类型。 - Hallgrim
如果您需要指定一个输出参数,请不要更改修饰符,那样行不通(对我来说)。您需要传递类型对象,并将其IsByRef属性设置为true。虽然IsByRef是只读的,但您需要使用类型的MakeByRefType方法将类型转换为具有此属性设置的实例。 - Martin Maat

17

是的。当您调用方法时,请传递与您想要重载匹配的参数。

例如:

Type tp = myInstance.GetType();

//call parameter-free overload
tp.InvokeMember( "methodName", BindingFlags.InvokeMethod, 
   Type.DefaultBinder, myInstance, new object[0] );

//call parameter-ed overload
tp.InvokeMember( "methodName", BindingFlags.InvokeMethod, 
   Type.DefaultBinder, myInstance, new { param1, param2 } );

如果您采用另一种方式(即通过查找MemberInfo并调用Invoke)进行操作,请注意获取正确的结果-无参数重载可能是第一个找到的。


有趣的是,这并没有起作用。我没有向我的无参数方法传递任何参数,但我仍然得到了一个模棱两可的调用。 - Wes P
这个如何处理不同类型的参数?比如我有两个重载函数,一个接受字符串,另一个接受整数? - smaclell
没问题 - 检查的是参数的基础类型。 - Keith
需要注意的是当你有可以隐式转换的类型时,.Net 会选择实例方法而不是继承方法。 - Keith
阅读了其他回答之后,哪种方法是首选?我应该依靠InvokeMember来检查底层类型吗?还是应该通过Type.GetMethod进行调用,并明确指定参数的类型?我认为后者能够节省运行时的一些工作...? - Wes P
显示剩余2条评论

5
使用带有System.Type[]参数的GetMethod重载方法,并传递一个空的Type[]。
typeof ( Class ).GetMethod ( "Method", new Type [ 0 ] { } ).Invoke ( instance, null );

3
你可以使用 Type.EmptyTypes。 - yoel halb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接