当前位置: 首页 > 编程语言 > C#

检查是否在使用反射的方法中调用了方法Share

时间:2023-04-11 11:25:38 C#

检查是否在使用反射的方法中调用了方法我正在使用反射,目前有一个MethodBody。如何检查MethodBody中是否调用了特定方法?程序集assembly=Assembly.Load("Module1");输入type=assembly.GetType("Module1.ModuleInit");MethodInfomi=type.GetMethod("初始化");方法体mb=mi.GetMethodBody();使用单声道。塞西尔。它是一个在Microsoft.NET和Mono上运行的独立程序集。(我想我在编写下面的代码时使用的是0.6或更高版本)假设您有许多IEnumerable程序集;使用AssemblyFactory获取这些(加载一个?)以下代码段将枚举这些程序集的所有类型集中方法的所有用法methodUsages=assemblys.SelectMany(assembly=>assembly.MainModule.Types.Cast()).SelectMany(type=>type.Methods.Cast()).Where(method=>null!=method.Body)//允许抽象和泛型.SelectMany(method=>method.Body.Instructions.Cast()).Select(instr=>instr.Operand).OfType();这将返回对该方法的所有引用(因此包括在反射中使用,或构造可能执行或可能不执行的表达式)。所以这可能不是很有用,除了向您展示CecilAPI可以轻松完成的工作之外:)请注意,此示例假定使用旧版本的Cecil(主流单声道版本中的版本)。较新的版本当然适用于您的情况,您可以使用单个方法参考作为起点。假设你想检测什么时候可以在'startingpoint':MethodReferencestartingpoint中直接调用'mytargetmethod';//使用CecilMethodReferencemytargetmethod在某处获取它;//你在找什么boolisCalled=startingpoint.GetOriginalMethod()//跳转到原始(例如泛型).Resolve()//从IL图像中获取定义.Body.Instructions.Cast().Any(i=>i.OpCode==OpCodes.Callvirt&&i.Operand==(mytargetmethod));CallTreeSearch这是一个工作片段,它允许您递归搜索(选定的)相互(间接)调用的方法。使用系统;使用系统集合;使用System.Collections.Generic;使用System.Linq;使用Mono.Cecil;使用Mono.Cecil.Cil;namespaceStackOverflow{/**广度优先惰性搜索遍及以startingPoint为根的调用树的子集**methodSelect选择要递归到的方法*resultGen生成要由枚举器返回的结果对象**/classCallTreeSearch:BaseCodeVisitor,IEnumerablewhereT:class{privatereadonlyFunc_methodSelect;私有只读函数,T>_transform;私有只读IEnumerable_startingPoints;privatereadonlyIDictionary>_chain=newDictionary>();privatereadonlyICollection_seen=newHashSet(newCompareMembers());私有只读ICollection_results=newHashSet();私有堆栈_currentStack;私有constintInfiniteRecursion=-1;私有只读int_maxrecursiondepth;私人布尔_busy;publicCallTreeSearch(IEnumerablestartingPoints,FuncmethodSelect,Func,T>resultGen):this(startingPoints,methodSelect,resultGen,InfiniteRecursion){}publicCallTreeSearch(IEnumerablestartingPoints,FuncmethodSelect,Func,T>resultGen,intmaxrecursiondepth){_startingPoints=startingPoints.ToList();}_methodSelect=方法选择;_maxrecursiondepth=maxrecursiondepth;_transform=结果生成;}publicoverridevoidVisitMethodBody(MethodBodybody){_seen.Add(body.Method);//避免无限递归base.VisitMethodBody(body);}publicoverridevoidVisitInstructionCollection(InstructionCollectioninstructions){foreach(Instructioninstructininstructions)VisitInstruction(instr);base.VisitInstructionCollection(说明);}publicoverridevoidVisitInstruction(Instructioninstr){Tresult=_transform(instr,_currentStack);如果(结果!=null)_results.Add(结果);varmethodRef=instr.OperandasMethodReference;//TODO仅选择调用?如果(methodRef!=null&&_methodSelect(methodRef)){varresolve=methodRef.Resolve();if(null!=resolve&&!(_chain.ContainsKey(resolve)||_seen.Contains(resolve)))_chain.Add(resolve,newStack(_currentStack.Reverse()));}base.VisitInstruction(instr);}publicIEnumeratorGetEnumerator(){lock(this)//不是多线程安全的{if(_busy)thrownewInvalidOperationException("CallTreeSearchenumeratorisnotreentrant");_busy=真;尝试{int递归级别=0;ResetToStartingPoints();while(_chain.Count>0&&((InfiniteRecursion==_maxrecursiondepth)||recursionLevel++>(_chain);_chain.Clear();foreach(varcallinclone.Where(call=>HasBody(call.Key))){//Console.Error.Write("rCallTreeSearch:level#{0},scanning{1,-20}r",recursionLevel,call.Key.Name+newstring('',21));_currentStack=call.Value;_currentStack.Push(call.Key);try{_results.Clear();call.Key.Body.Accept(this);//增长_chain和_results}finally{_currentStack.Pop();}_currentStack=nu二;foreach(varresultin_results)产生返回结果;}}}最后{_busy=false;}}}privatevoidResetToStartingPoints(){_chain.Clear();_seen.Clear();foreach(varstartingPointin_startingPoints){_chain.Add(startingPoint,newStack());_seen.Add(起点);}}privatestaticboolHasBody(MethodDefinitionmethodDefinition){return!(methodDefinition.IsAbstract||methodDefinition.Body==null);}IEnumeratorIEnumerable.GetEnumerator(){返回GetEnumerator();}}内部类CompareMembers:IComparer,IEqualityComparerwhereT:class,IMemberReference{publicintCompare(Tx,Ty){returnStringComparer.InvariantCultureIgnoreCase.Compare(KeyFor(x),KeyFor(y));}publicboolEquals(Tx,Ty){returnKeyFor(x).Equals(KeyFor(y));}privatestaticstringKeyFor(Tmr){返回null==mr?"":String.Format("{0}::{1}",mr.DeclaringType.FullName,mr.Name);}publicintGetHashCode(Tobj){returnKeyFor(obj).GetHashCode();注意典型用法:publicstaticIEnumerableSearchCallTree(thisTypeDefinitionstartingClass,FuncmethodSelect,Func,T>resultFunc,intmaxdepth)whereT:class{returnnewCallTreeSearch(startingClass.Methods.Cast(),methodSelect,resultFunc,maxdepth);}publicstaticIEnumerableSearchCallTree(thisMethodDefinitionstartingMethod,FuncmethodSelect,Func,T>resultFunc,intmaxdepth)whereT:class{returnnewCallTreeSearch(new[]{startingMethod},methodSelect,maxdepthnc);}//实际用法:privatestaticIEnumerableSearchMessages(TypeDefinitionuiType,boolonlyConstructions){returnuiType.SearchCallTree(IsBusinessCall,(instruction,stack)=>DetectRequestUsage(instruction,stack,onlyConstructions));请注意,像DetectRequestUsage函数这样的DetectRequestUsage完全可以满足您的需求(编辑:但请参阅此处)您可以做任何您想做的事情,不要忘记:您将拥有完整的静态分析调用堆栈,因此您实际上可以做一些漂亮的事情!在生成代码之前,您必须检查它是否已经存在。在某些情况下,捕获异常比阻止异常生成的成本更低。这是一个很好的例子。您可以获得方法体的IL,但Reflection不是反汇编程序。反汇编程序也不是真正的修复,您可以反汇编整个调用树以实现您想要的行为。毕竟,文字中的方法调用本身可以调用方法,等等。在编译IL时捕捉抖动抛出的异常就简单多了。您可以使用StackTrace类:System.Diagnostics.StackTracest=newSystem.Diagnostics.StackTrace();System.Diagnostics.StackFramesf=st.GetFrame(1);Console.Out.Write(sf.GetMethod().ReflectedType.Name+"."+sf.GetMethod().Name);可以调1,确定自己感兴趣的帧数,以上是C#学习教程:检查是否在使用反射的方法中调用方法,所有内容分享,如果对大家有用需要了解更多关于C#学习教程,希望大家多多关注——本文采集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢