我正在尝试修改Microsoft Roslyn编译器来执行超出所提供API范围的一些奇怪的事情.但我对罗斯林来说是全新的,罗斯林是庞大的(460万行代码),我发现很难找到它的方法.
具体来说,我想找到发出".class"IL语句的位置,并且通常是执行C#类的最终编译,即类的外部结构.(我发现内部的东西像方法和表达式一样.)
编辑:
@nejcs是正确的,在发出的代码中没有".class"IL语句这样的东西.当你使用.Net Reflector或dotPeek时,我错误地想到了你所看到的.
我将尝试更详细地解释我正在尝试做什么,以及我正在寻找什么,希望能让我做我想做的事情.
考虑一个简单的C#类,如下所示:
public static class Yacks00020001
{
public static readonly string s;
static Yacks00020001()
{
s = YacksCore.M0002("Hello world!", 42);
}
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是在发射器处理期间"创建"并在运行中发出大量这些静态对象(显然具有不同的名称和不同的字符串).我希望通过创建足够的模拟数据来"欺骗"发出类声明,方法和语句的发射器方法,并使用此模拟输入调用它们.
我想在编译期间我找到了描述C#类声明的对象,它在这里:
它在这里创建:
但我不是百分百肯定的.
尽管@nejcs在他的回答中提供了很好的信息,但我仍然无法在发射器处理中找到发出类声明的位置.
没有.classIL声明.你所指的是用于类声明的IL汇编程序(ilasm)指令.程序集中类的实际声明在特定部分中,并且不由任何关键字标识.对于CLR部分的详细解释,我建议阅读第1部分和第2部分.
由于类只是声明,因此也没有类的编译.只有当您想要发送到PE流时,您必须检索所有声明的类型,方法和其他对象,以将它们写入流内的正确位置.所以编译就是这样的:
PEAssemblyBuilder存储对compilation的源程序集符号的引用,该符号包含所有其他符号,包括类.CompileAndEmit 调用方法体的编译并将结果存储到模块构建器.CompileAndEmit 请将模块构建器序列化为PE流.在一些设置之后调用SerializePeToStream,它EmitContext使用模块构建器引用创建,该引用被传递给元数据编写器.Writer使用模块构建器来提取有关类和其他对象的信息,并为最终存储创建适当的索引.简而言之Compilation(CSharpCompilation对于C#代码)为程序集构建器提供源程序集符号,然后传递它并可以查询各种对象.我不知道你想要实现什么,但你可能想要修改内部存储的内容Compilation,因为管道中没有太多的逻辑.不过,我可能错过了一些东西.
编辑
基于问题编辑,我将更详细地描述元数据编写器如何提取有关类的信息.为了简化,我将专注于编写完整的元数据并忽略差异元数据.
SerializePeToStreamMethod,则会创建完整的元数据编写器并调用BuildMetadataAndIL.CreateIndicesForModule通过最终调用GetTopLevelType来检索顶级类型.您可以看到有多种类型被检索但我们对方法感兴趣.CommonPEModuleBuilderGetTopLevelTypesCore至于你的具体问题,我仍然认为最好生成有效的编译对象(使用正确的符号)并保持发射相位不变.否则,您必须非常小心数据处于一致状态,否则您将获得异常或无效的PE.
| 归档时间: |
|
| 查看次数: |
193 次 |
| 最近记录: |