到目前为止,我一直在寻找这个,但是没有运气.是否有相当于.NET的
ClassFileTransformer
?基本上,我想创建一个类CustomClassFileTransformer(在Java中实现接口ClassFileTransformer),只要加载一个类就会调用它,并允许调整它并用调整后的版本替换它.
我知道有些框架可以做类似的事情,但我正在寻找更直接的东西,比如实现我自己的ClassFileTransformer.可能吗?
编辑#1.关于我为什么需要这个的更多细节:
基本上,我有一个C#应用程序,我需要监视它想要运行的指令,以便检测字段的读或写操作(操作Ldfld
和Stfld
),并在读/写发生之前插入一些指令.
我知道如何做到这一点(除了需要调用以替换类的部分):对于我想要监视其代码的每个方法,我必须:
>使用MethodBase.GetMethodBody()
获取方法MethodBody
>使用MethodBody.GetILAsByteArray()
将其转换为字节数组.它返回的byte []包含字节码.
>按照here的说明分析字节码,可能通过更改数组的内容插入新指令或删除/修改现有指令.
>创建一个新方法并使用新的字节码创建它的主体,使用MethodBuilder.CreateMethodBody(byte[] il, int count)
,其中il是带字节码的数组.
我将所有这些调整过的方法放在一个新类中,并使用新类替换最初要加载的类.
替换类的替代方法将以某种方式在调用方法时得到通知.然后我用调用我自己的调整方法替换对该方法的调用,我只会在第一次调用时进行调整,然后我将它放在字典中以备将来使用,以减少开销(对于将来的调用)我只是查找方法并调用它;我不需要再次分析字节码).我正在研究如何做到这一点,LinFu看起来很有趣,但如果有类似ClassFileTransformer的东西会更简单:我只是重写类,替换它,让代码运行而不监视任何东西.
附加说明:课程可以密封.我希望能够替换任何类,我不能对其属性施加限制.
编辑#2.为什么我需要在运行时执行此操作.
我需要监控正在发生的一切,以便我可以检测每次访问数据.这也适用于库类的代码.但是,我事先无法知道将要使用哪些类,即使我知道可能加载的每个可能的类,但是调整所有类而不是等待查看它们是否实际被调用或不.
可能(但纯粹的硬核)解决方案.如果有人感兴趣(我看到这个问题已经存在,所以我猜有人会这样),this就是我现在正在看的东西.基本上我必须实现分析API,我将注册我感兴趣的事件,就我的情况而言,每当JIT编译开始时.博文摘录:
>在ICorProfilerCallback2 :: ModuleLoadFinished回调中,调用ICorProfilerInfo2 :: GetModuleMetadata以获取指向该模块上元数据接口的指针.
>您想要的元数据接口的QI.在MSDN中搜索“IMetaDataImport”,并浏览目录以查找元数据接口上的主题.
>一旦进入元数据域,就可以访问模块中的所有类型,包括其字段和函数原型.您可能需要解析元数据签名,并且此签名解析器可能对您有用.
>在ICorProfilerCallback2 :: JITCompilationStarted回调中,您可以使用ICorProfilerInfo2 :: GetILFunctionBody来检查原始IL,然后使用ICorProfilerInfo2 :: GetILFunctionBodyAllocator,然后使用ICorProfilerInfo2 :: SetILFunctionBody将IL替换为您自己的IL.
好消息:当JIT编译开始时我得到通知,我可以在那里替换字节码,而不必担心替换类等等.不太好的消息:你不能从API的回调方法中调用托管代码这有意义,但意味着我自己解析IL代码等,而不是能够使用Cecil,这将是一件轻而易举的事.
我不认为在不使用AOP框架(例如PostSharp)的情况下更简单的方法.如果有人有任何其他想法,请告诉我.我还没有回答这个问题.
最佳答案 我不知道.NET中的直接等价物.
但是,有一些方法可以实现类似的功能,例如使用Reflection.Emit按需生成程序集和类型,使用RealProxy为接口和MarshalByRefObject对象创建代理对象.但是,要建议使用什么,了解有关实际用例的更多信息非常重要.