假设我有以下不允许更改的课程:
public class C
{
public C() { CreateSideEffects(); }
public void M() { DoSomethingUseful(); }
}
我必须在不调用构造函数的情况下调用 M 。可能吗?
假设我有以下不允许更改的课程:
public class C
{
public C() { CreateSideEffects(); }
public void M() { DoSomethingUseful(); }
}
我必须在不调用构造函数的情况下调用 M 。可能吗?
即使这不是一个好主意,是的,我们可以 ;) 使用FormatterServices。获取未初始化对象。
C uninitializedC = (C)FormatterServices.GetUninitializedObject(typeof(C));
uninitializedC.M();
不行,因为C.M()
是实例方法,所以需要创建实例,也就是调用构造函数。
是C
您的团队拥有的课程吗?如果是这样,但你被命令不要管它,你最好游说以下任何一个:
C.M()
方法功能移出到另一个类或变为静态。如果C
来自第 3 方,您将遇到麻烦,并且可能必须以您拥有的方法复制的C.M()
功能。
是的你可以!
不用说这是一个糟糕的设计,但是您已经知道并且无法更改它。如果必须,您可以尝试部分模拟课程。
编辑:刚刚意识到我的示例使用 Java 而不是 C#。但是,@Guillaume 提供了 C# 的代码示例。显然,它甚至内置在运行时 API 中!
在 Java 中,使用Mockito,这确实有效:
C c = Mockito.mock(C);
Mockito.doCallRealMethod().when(c).M();
// If M() isn't a void method
// when(c.M()).thenCallRealMethod();
c.M();
但是,在这种情况下M()
,不能依赖于构造函数中设置的任何状态。
有关部分模拟的更多信息,请查看此常见问题解答问题。但是,模拟主要用于测试。
为了调用实例方法,您需要一个实例!而且 - 有充分的理由 - 获得一个的唯一方法是通过构造函数。否则,由于尚未进行初始化,整个对象可能处于不确定或无用状态。所以就算有什么hack,也不是什么好选择!
唯一可以在没有实例的情况下调用的类成员是静态方法。
我不会告诉你这是一个坏主意,因为听起来你已经被告知得够多了。哦,对不起,我想我刚刚做了......无论如何,这里是如何做到的:
using System.Runtime.Serialization;
C myInstance = FormatterServices.GetUninitializedObject(typeof(C));
myInstance.M();
上面的“GetUninitializedObject”方法返回一个对象的实例,而不调用任何实例 ctor(显然任何静态类型 ctor 仍将运行)。然后,您可以根据需要戳实例字段或简单地调用方法。
再次,作为一个整体的坏主意;)