我想编写一个规则,如果在标记有特定属性的方法调用的任何方法中进行对象分配,该规则将失败。
到目前为止,我已经通过迭代调用我的方法的所有方法来使用 CallGraph.CallersFor()
进行检查,以查看是否有任何父方法具有该属性。
这适用于检查与要检查的方法相同的程序集中的父方法,但是在线阅读,似乎有一次 CallGraph.CallersFor()
确实查看了所有程序集,但是现在它没有。
问题有没有办法获取调用给定方法的方法列表,包括不同程序集中的方法?
替代答案:如果以上不可能,我如何遍历给定方法调用的每个方法,包括不同程序集中的方法。
示例:
-----In Assembly A
public class ClassA
{
public MethodA()
{
MethodB();
}
public MethodB()
{
object o = new object(); // Allocation i want to break the rule
// Currently my rule walks up the call tree,
// checking for a calling method with the NoAllocationsAllowed attribute.
// Problem is, because of the different assemblies,
// it can't go from ClassA.MethodA to ClassB.MethodB.
}
}
----In Assembly B
public var ClassAInstance = new ClassA();
public class ClassB
{
[NoAllocationsAllowed] // Attribute that kicks off the rule-checking.
public MethodA()
{
MethodB();
}
public MethodB()
{
ClassAInstance.MethodA();
}
}
我真的不介意规则在哪里报告错误,在这个阶段得到错误就足够了。
最佳答案
我通过在我的 FxCop 项目中添加所有引用的 dll 并使用下面的代码来解决这个问题,该代码手动构建调用树(它还添加了对派生类的调用以解决我遇到的另一个问题 here。
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;
}
}
关于c# - 确定一个方法是否调用另一个包含新语句的程序集中的方法,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6439376/