1

嗨,我正在取消 NDepend 以对我的代码进行一些分析。我想从我的代码库中获取所有调用某个方法的方法,但我观察到它没有按我预期的那样工作。

以下是我的观察:

在我的代码中,我有:

1.) 带有方法 Method1 的接口 IMyInterface

public interface IMyInterface {
    void Method1();
}

2.) 实现上述接口的类

public class MyClass : IMyInterface {
    public void Method1() {
        // Implementation
    }
}

3.)在我的程序代码的某个地方,我有一个方法可以执行以下操作

public void MethodCaller() {
    IMyInterface instance = new MyClass();
    instance.Method1();
}

现在,使用NDepend,我观察到以下内容:

我得到了MyClass.Method1方法的 IMethod 实例,例如method1Info和它的 MethodsCallingMe属性返回0结果。

method1Info.MethodsCallingMe 计数为 0。

如果我获得 IMyInterace.Method1 方法的 IMethod 实例 MethodsCallingMe属性返回1MethodCaller

我正在寻找一种方法来查找所有调用某个方法实现的方法,无论它是通过哪种类型调用的。我无法使用 MethodsCallingMe 实现这一点。我怎样才能做到这一点?

4

1 回答 1

0

确实在您的上下文中:

from m in Methods where m.IsUsing ("MyNamespace.IMyInterface.Method1()") select m

...返回MyNamespace.CallerClass.MethodCaller()和...

from m in Methods where m.IsUsing ("MyNamespace.MyClass.Method1()") select m

...什么都不返回。原因很简单:NDepend 做静态分析,不尝试做动态分析。因此,它不会尝试查看谁实现了抽象方法,即使在上下文中可以毫无歧义地推断出MethodCaller()变量的类型类。instance

然而,由于NDepend 代码查询语言非常灵活,以下代码查询可以检测您的情况并提供您想要的结果。请注意,可以匹配误报,但这将是一个经过调整的案例。

// Gather the abstract method
let mAbstract = Application.Methods.WithFullName("MyNamespace.IMyInterface.Method1()").Single()

from m in Methods where m.IsUsing(mAbstract)

// Get ctors called by MethodCaller()
let ctorsCalled = m.MethodsCalled.Where(mc => mc.IsConstructor)

// Get classes that implement IMyInterface instantiated by MethodCaller()
let classesInstantiated = ctorsCalled.ParentTypes().Where(t => t.Implement("MyNamespace.IMyInterface"))

// Get override of Method1() 'probably' called.
let overridesCalled = classesInstantiated.ChildMethods().Where(m1 => m1.OverriddensBase.Contains(mAbstract))

select new { m, overridesCalled }

具体来说,这看起来像:

在此处输入图像描述


附带说明一下,能够毫不含糊地推断出通过接口引用的对象的类是例外而不是规则,因为字段和方法参数通常是通过接口引用的,并且不包含有关它们如何的任何信息实例化。


我使用的代码:

namespace MyNamespace {
    public interface IMyInterface {
        void Method1();
    }
    public class MyClass : IMyInterface {
        public void Method1() {
            // Implementation
        }
    }
    public class CallerClass {
        public void MethodCaller() {
            IMyInterface instance = new MyClass();
            instance.Method1();
        }
    }
}
于 2013-10-01T10:25:07.903 回答