Indeed in your context:
from m in Methods where m.IsUsing ("MyNamespace.IMyInterface.Method1()") select m
...returns MyNamespace.CallerClass.MethodCaller()
and ...
from m in Methods where m.IsUsing ("MyNamespace.MyClass.Method1()") select m
...returns nothing. The reason is simple: NDepend does static analysis and doesn't try to do dynamic analysis. Hence it doesn't try to look who implements an abstract method, even if in the MethodCaller()
context type class of the variable instance
can be inferred without any ambiguity.
However since NDepend code query language is pretty flexible, the following code query can detect your case and provide the result you wish. Notice that false positive can be matched, but it would be a pretty tweaked case.
// 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 }
Concretely this look like:
As a side note, being able to infer without ambiguity the class of an object referenced through an interface is more the exception than the rule, since often fields and methods parameters are referenced through an interface and doesn't hold any information about how they are instantiated.
The code I used:
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();
}
}
}