ClassFileTransformer
相当的东西?基本上,我想创建一个类 CustomClassFileTransformer
(在Java中将实现接口ClassFileTransformer
),每当加载类时就会调用它,并且允许对其进行微调并用微调版本替换它。我知道有一些类似的框架,但我正在寻找更简单直接的东西,就像实现自己的
ClassFileTransformer
一样。这可能吗?
编辑 #1。我需要这个的更多细节:
基本上,我有一个C#应用程序,我需要监视它想要运行的指令,以便检测对字段进行读取或写入操作 (操作 Ldfld
和 Stfld
),并在读/写发生之前插入一些指令。
我知道如何做到这一点(除了需要被调用来替换类的部分):对于我想要监视其代码的每个方法,我必须:
- 使用
MethodBase.GetMethodBody()
获取方法的MethodBody
。 - 使用
MethodBody.GetILAsByteArray()
将其转换为字节数组。它返回的byte[]
包含字节码。 - 根据这里所述分析字节码,可能通过更改数组的内容插入新指令或删除/修改现有指令。
- 创建一个新方法,并使用新的字节码创建其主体,使用
MethodBuilder.CreateMethodBody(byte[] il, int count)
,其中il
是带有字节码的数组。我将所有这些调整过的方法放在一个新类中,并使用新类替换原本要加载的类。
ClassFileTransformer
这样的东西,那就简单得多了:我只需重写类,替换它,然后让代码运行而无需监视任何内容。
另外需要注意的是,这些类可能是 sealed 的。我希望能够替换任何类型的类,我不能对它们的属性施加限制。
编辑 #2。为什么我需要在运行时执行此操作。
我需要监视一切,以便能够检测到对数据的每次访问。这也适用于库类的代码。然而,我无法预先知道哪些类将被使用,即使我知道每个可能被加载的类,也将对所有类进行调整而不是等待看它们是否实际被调用,这将对性能造成巨大影响。
可能的解决方案(但相当难以实现)。如果有人感兴趣(我看到这个问题已经被收藏了,所以我猜有人是),this 是我现在正在查看的内容。基本上,我必须实现分析 API,并注册我感兴趣的事件,对于我的情况,每当 JIT 编译开始时。以下是该博客文章的摘录:
- 在你的ICorProfilerCallback2 :: ModuleLoadFinished回调中,调用ICorProfilerInfo2 :: GetModuleMetadata以获取该模块上的元数据接口指针。
- 查询“IMetaDataImport”以查找所需的元数据接口。并浏览目录以查找有关元数据接口的主题。
- 一旦进入元数据领域,您就可以访问模块中的所有类型,包括它们的字段和函数原型。您可能需要解析元数据签名,此签名解析器可能对您有所帮助。
- 在ICorProfilerCallback2 :: JITCompilationStarted回调中,您可以使用ICorProfilerInfo2 :: GetILFunctionBody检查原始IL,并使用ICorProfilerInfo2 :: GetILFunctionBodyAllocator和ICorProfilerInfo2 :: SetILFunctionBody替换自己的IL。
好消息是:当JIT编译开始时,我会收到通知,并且可以在那里直接替换字节码,无需担心替换类等。不太好的消息是:您无法从API的回调方法中调用托管代码,这很合理,但意味着我必须自己解析IL代码等,而不能使用Cecil,这将是轻松愉快的。
我认为没有不使用AOP框架(例如PostSharp)更简单的方法来做到这一点。如果有其他想法,请告诉我。我还没有将问题标记为已回答。