.NET反射:如何在不创建实例的情况下调用接口方法?

8

我有一个情况,需要使用反射调用接口的方法,就像这样:

object x = null;
MethodInfo method = interfaceExists.GetMethod("ShutDown");
method.Invoke(x, new object[] { 4 })

您可以看到,我没有创建对象实例!而且,我猜测,我会收到异常

非静态方法要求有一个目标

问题是,我能否在不创建接口实例的情况下使用反射调用接口方法?如果可以,我该如何做呢?


这样想:如果你能调用这个方法,它实际上会做什么? - Aaronaught
6个回答

13
如果你确信接口方法不会影响对象状态(通常这是一个非常糟糕的假设),那么可以通过调用FormatterServices.GetUnitializedObject来创建一个未调用构造函数的实例。个人而言,我强烈建议不要这样做,因为在未初始化类型上调用接口方法可能会发生许多糟糕的事情。

谢谢,这对我来说可能是合理的。 - jitm

10

如果是实例方法,您需要一个实例来调用该方法。因此称之为“实例”方法。

实例方法可能依赖于实例变量,反射无法了解这些变量,因此无法保证实例方法不会更改其所定义类型的实例的状态。

这就是为什么您会收到 FxCop 警告的原因(在此进行了转述):“将此方法设置为静态方法,因为它不会更改类的状态”。


如何将接口的方法设为静态? - jitm
你不能在接口上拥有静态方法。如果你不想让该类被使用,你需要在一个类中使用静态方法,并将其标记为抽象类,然后实现该接口,并从中派生出子类。 - Ian
@jitm,你不能这样做。如果你真的非常需要这样做,考虑放弃接口而使用基类。当然,你不能覆盖基类的静态方法,所以你可能仍然会遇到问题。尝试在SO上提出另一个问题(不要使用这个),详细说明你想做什么,并询问是否有更好的方法。 - user1228
是的,我明白这个问题,所以我才问。非常感谢所有的回答。 - jitm
当然,如果您正在使用反射,您实际上并不需要接口;只需要一个模式。您的概念界面可以简单地是“一个名为XYZ_interface_Method的静态方法,带有一个整数参数”。 - Eamon Nerbonne

4

如果方法是非静态的,您需要创建一个对象实例来使用它。由于接口不能有静态方法,因此您需要创建一个带有接口的对象实例来执行该方法。


2

您的非静态接口方法最终需要调用已实现于对象上的方法。如果该方法的实现不存在,则无法调用真正的方法。


1

你能在不创建实例的情况下调用接口方法吗? 不行。接口是针对实例成员的;静态类成员与接口无关。

您可以通过提供接口的静态实现来获得所需的内容,

public class MyImplementation : IMyInterface
{
    public static readonly Instance = new MyImplementation();
    private MyImplementation() { }
}
// ...then your code might look like:
MethodInfo method = typeof(IMyInterface).GetMethod("ShutDown");
method.Invoke(MyImplementation.Instance, new object[] { 4 })

或者你可以创建一个扩展方法:

public static class MyExtensions
{
    public static void ShutDown(this IMyInterface obj, ...) { ... }
}
// ...then your code might look like:
object x = null;
MethodInfo method = typeof(MyExtensions).GetMethod("ShutDown");
method.Invoke(x as IMyInterface, new object[] { 4 });

1

接口没有实现,因此您无法在未实现该接口的对象实例中调用其方法。


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