Determining how to invoke a method in another assembly containing a new expression and vice versa

I want to write a rule that will not be executed if the selection of the object is performed in any method called by the method marked with a certain attribute.

I have got this job so far, iterating through all the methods that call my method, to check with CallGraph.CallersFor() to find out if any of these parent methods have this attribute.

This works for checking parent methods in the same assembly as the method being checked, but reading online it seems that CallGraph.CallersFor() once CallGraph.CallersFor() through all the assemblies, but now it is not.

Question: Is there a way to get a list of methods that call this method, including in another assembly?

Alternative answer: If the above is not possible, how do I go through each method that is called by this method, including in another assembly.


Example:

 -----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(); } } 

I really don't mind when a rule reports an error, at this point it is enough to get an error.

+8
c # fxcop call-graph
source share
2 answers

I circumvented this problem by adding all the related DLLs to my FxCop project and using the code below, which builds a call tree manually (it also adds calls for derived classes to work around another problem that I encountered,.

 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; } } 
+2
source share

You tried this way

  StackTrace stackTrace = new StackTrace(); MethodBase methodBase = stackTrace.GetFrame(1).GetMethod(); object [] items = methodBase.GetCustomAttributes(typeof (NoAllocationsAllowed)); if(items.Length > 0) //do whatever you want! 
0
source share

All Articles