我正在寻找一种方法来确保方法'A'调用方法'B'。粗略地说,这笔交易是......
class one
{
internal static void MethodA()
{
//Do Something here. SHOULD be calling B.
}
void MethodB()
{
//MUST be called by MethodA.
}
}
class two
{
internal void MethodA()
{
//Test that MethodA calls MethodB
}
}
我应该指出,我坚持使用.Net 2.0,所以ExpressionTrees是不行的。我甚至不确定他们会帮忙,但这是我最初的想法。
编辑:这是一个内部工具可视化源的圈复杂度,所以我不关心破坏封装。此外,..这可能只需要使用System.Reflection来完成。
答案 0 :(得分:4)
在许多情况下这是可行的,但是你需要打字。您要做的第一件事是使用ILReader类 - 有one here(和the one that Florian Doyon posted)的大纲。然后你想把它包装在这样的类中:
public class MethodCalls : IEnumerable<MethodInfo>
{
MethodBase _method;
public MethodCalls(MethodBase method)
{
_method = method;
}
public IEnumerator<MethodInfo> GetEnumerator()
{
// see here: http://blogs.msdn.com/haibo_luo/archive/2005/10/04/476242.aspx
ILReader reader = new ILReader(_method);
foreach (ILInstruction instruction in reader) {
CallInstruction call = instruction as CallInstruction;
CallVirtInstruction callvirt = instruction as CallVirstInstruction;
if (call != null)
{
yield return ToMethodInfo(call);
}
else if (callvirt != null)
{
yield return ToMethodInfo(callvirt);
}
}
}
}
MethodInfo ToMethodInfo(CallInstruction instr) { /* ... */ }
MethodInfo ToMethodInfo(CallVirtInstruction instr) { /* ... */ }
这两种ToMethodInfo都没有定义,因为CallInstruction也没有定义。尽管如此,这个大纲有望将您的问题转化为:
public static bool Calls(MethodBase caller, MethodInfo callee)
{
return new MethodCalls(caller).Contains(callee);
}
答案 1 :(得分:2)
您可以使用Mono Cecil反映MethodA
的方法正文,并查找调用call/callvirt
的{{1}}条指示。
答案 2 :(得分:2)
答案 3 :(得分:1)
可能不是您正在寻找的,但您可以使用模拟框架编写单元测试。该模拟框架(例如Moq)可以验证在执行某些代码时是否在模拟中调用了一个方法。
答案 4 :(得分:1)
老实说,我认为你对课堂内部细节的实施过于痴心。
至于答案,我提供了一个对应点,考虑:
void MethodB() {
var methodA = BuildDelegate("Method" + "A");
methodA();
}
答案 5 :(得分:1)
你不能用手滚动模拟对象吗?这取决于你是否可以使MethodB可见和虚拟。
class one
{
internal static void MethodA()
{
//Do Something here. SHOULD be calling B.
}
internal virtual void MethodB()
{
//MUST be called by MethodA.
}
}
class three : one
{
public bool wasCalled;
override void MethodB()
{
wasCalled=true;
}
}
class two
{
internal void MethodA()
{
three.ClassA();
if (three.wasCalled)
{
}
}
}