如何获取FxCop中callvirt IL指令实际调用的方法 [英] How to get the method actually called by the callvirt IL instruction within FxCop
问题描述
我仍然试图让我的FxCop规则正常工作。
I'm still trying to get my FxCop rule working.
作为其中的一部分,我需要弄清楚方法调用的方法。以前我使用 CallGraph.CallersFor()
(反过来做,这是我最后的目标),但它似乎有我在下面描述的相同问题。
As part of this, i need to work out what methods a method calls. Previously i was using CallGraph.CallersFor()
(doing it in reverse, which is my final aim anyway), however it appears to have the same issue i describe below.
作为使用 CallGraph
类的替代方法,我尝试访问所有方法调用以构建字典,基于以下代码:
As an alternative to using the CallGraph
class i tried visiting all method calls to build a dictionary, based on this code:
public override void VisitMethodCall(MethodCall call)
{
Method CalledMethod = (call.Callee as MemberBinding).BoundMember as Method;
// ....
}
但事实证明,如果被调用的方法在一个覆盖基类的方法的派生类上,则 BoundMember
是基类'方法,而不是子类'方法(这是一个实际上会被调用的。)
However, it turns out that if the called method is on a derived class that overrides a base class' method, then the BoundMember
is the base class' method, not the child class' method (which is the one that will actually be called).
问题:如何获得将在callvirt IL指令的情况下调用的方法在FxCop?
Question: How can i get the method that will be called in the case of a callvirt IL instruction in FxCop?
推荐答案
在我的情况下,我实际上并不需要这个(这很好因为我不喜欢在这种情况下,我有一个确切的答案。)
Turns out in my case that i don't actually need this exactly (which is good because i don't have an exact answer in this case).
因为FxCop是一个静态检查器,它永远不会知道变量指向的对象实例的类型,可以声明为基本类型。因此,我相信我所要求的是不可能的。
Because FxCop is a static checker it can never know the type of the instance of the object pointed to by the variable, which could be declared as a base type. Therefore i believe what i'm asking for is impossible.
我的解决方案是,在构建调用树时,我为基类添加额外的引用'调用'任何派生类。这样,如果我在基类上调用一个方法,并且可以调用派生类的方法,我就可以按照这种方式跟随调用树。
My solution here, is to, when building the call tree, i add in extra references for a base class 'calling' any derived classes. In this way if i call a method on the base class, and the derived class' method could be called i can follow the call tree in that way.
见下文我的类由FxCop规则类使用:
See below for my class used by FxCop rule classes:
public class CallGraphBuilder : BinaryReadOnlyVisitor
{
public Dictionary<TypeNode, List<TypeNode>> ChildTypes;
public Dictionary<Method, List<Method>> CallersOfMethod;
private Method _CurrentMethod;
public CallGraphBuilder()
: base()
{
CallersOfMethod = new Dictionary<Method, List<Method>>();
ChildTypes = new Dictionary<TypeNode, List<TypeNode>>();
}
public override void VisitMethod(Method method)
{
_CurrentMethod = method;
base.VisitMethod(method);
}
public void CreateTypesTree(AssemblyNode Assy)
{
foreach (var Type in Assy.Types)
{
if (Type.FullName != "System.Object")
{
TypeNode BaseType = Type.BaseType;
if (BaseType != null && BaseType.FullName != "System.Object")
{
if (!ChildTypes.ContainsKey(BaseType))
ChildTypes.Add(BaseType, new List<TypeNode>());
if (!ChildTypes[BaseType].Contains(Type))
ChildTypes[BaseType].Add(Type);
}
}
}
}
public override void VisitMethodCall(MethodCall call)
{
Method CalledMethod = (call.Callee as MemberBinding).BoundMember as Method;
AddCallerOfMethod(CalledMethod, _CurrentMethod);
Queue<Method> MethodsToCheck = new Queue<Method>();
MethodsToCheck.Enqueue(CalledMethod);
while (MethodsToCheck.Count != 0)
{
Method CurrentMethod = MethodsToCheck.Dequeue();
if (ChildTypes.ContainsKey(CurrentMethod.DeclaringType))
{
foreach (var DerivedType in ChildTypes[CurrentMethod.DeclaringType])
{
var DerivedCalledMethod = DerivedType.Members.OfType<Method>().Where(M => MethodHidesMethod(M, CurrentMethod)).SingleOrDefault();
if (DerivedCalledMethod != null)
{
AddCallerOfMethod(DerivedCalledMethod, CurrentMethod);
MethodsToCheck.Enqueue(DerivedCalledMethod);
}
}
}
}
base.VisitMethodCall(call);
}
private void AddCallerOfMethod(Method CalledMethod, Method CallingMethod)
{
if (!CallersOfMethod.ContainsKey(CalledMethod))
CallersOfMethod.Add(CalledMethod, new List<Method>());
if (!CallersOfMethod[CalledMethod].Contains(CallingMethod))
CallersOfMethod[CalledMethod].Add(CallingMethod);
}
private bool MethodHidesMethod(Method ChildMethod, Method BaseMethod)
{
while (ChildMethod != null)
{
if (ChildMethod == BaseMethod)
return true;
ChildMethod = ChildMethod.OverriddenMethod ?? ChildMethod.HiddenMethod;
}
return false;
}
}
这篇关于如何获取FxCop中callvirt IL指令实际调用的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!