c# - 如何将加载的程序集提供给 C# 中的 Roslyn 工作区

标签 c# .net .net-assembly roslyn roslyn-code-analysis

我正在使用运行时代码生成来增强现有流程。我在运行时创建的代码需要访问创建代码的进程已经引用的一些相同的 dll。

问题是该进程在某些第 3 方软件中运行,这些软件从资源中加载 dll 并将它们注入(inject)我的进程中...因此我无法访问磁盘上的 dll,也无法访问包含 dll 的资源外部包装器。

因此,我尝试使用内存中已有的程序集,并将它们送入 Roslyn 工作区,我将运行时代码放入其中进行编译。 我想我可以按照这个 SO 尝试使用二进制格式化程序序列化程序集: Opposite operation to Assembly Load(byte[] rawAssembly)

但即使我几乎按原样使用代码:

Assembly yourAssembly = typeof(object).Assembly;
var formatter = new BinaryFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, yourAssembly);
var reloadedAssembly = Assembly.Load(ms.GetBuffer());

我得到:

An exception of type 'System.BadImageFormatException' occurred in mscorlib.dll but was not handled in user code

其他搜索结果似乎都好不到哪里去。

我想做的是这样的:

var assemblyRef = MetadataReference.CreateFromAssembly(typeof(object).Assembly);
mySolution.AddMetadataReference(projectId, assemblyRef);

有什么建议吗?

最佳答案

对于使用 Assembly.Load(byte[]) 加载的托管程序集,您可以像这样创建 Roslyn MetadataReference:

var assembly = Assembly.Load(bytes);
var modulePtr = Marshal.GetHINSTANCE(assembly.ManifestModule);

var peReader = new PEReader((byte*)modulePtr, bytes.Length))
var metadataBlock = peReader.GetMetadata();
var moduleMetadata = ModuleMetadata.CreateFromMetadata((IntPtr)metadataBlock.Pointer, metadataBlock.Length);
var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
var reference = assemblyMetadata.GetReference();

请注意,这不适用于从文件加载的程序集,因为内存中的布局不同。

关于c# - 如何将加载的程序集提供给 C# 中的 Roslyn 工作区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40476805/

相关文章:

c# - 使用 VB 的 FileSystem.DeleteFile 方法无法正常工作,将文件删除到 csharp 中的回收站

c# - 使用目标 :module switch 编译代码

c# - 如何防止程序集在不使用时加载

c# - 如何在 Azure 函数中调试 FileLoadException

c# - 如何以编程方式更新和保存 app.config 应用程序设置

c# - 根据 DateTime 左移计算优先级

c# - 加载 System.Web 失败但加载 System.Xml 成功

c# - 使用更指定的返回类型(协方差)覆盖抽象属性

c# - 检查字符串是否以列表中的任何字符开头

c# - 我的图像不会添加 C#