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

本文关键字:Roslyn 工作区 程序集 加载 | 更新日期: 2023-09-27 18:17:02

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

问题是进程运行在一些第三方软件中,这些软件从资源中加载dll并将它们注入到我的进程中…因此,我既不能访问磁盘上的dll,也不能访问外部包装器中包含dll的资源。

作为结果,我试图使用我已经在内存中拥有的程序集,并将它们提供给Roslyn工作空间,我将运行时代码放入其中进行编译。我想我可以尝试用二进制格式化程序序列化程序集,如下所示:与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);

有什么建议吗?

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

对于使用assembly . load (byte[])加载的托管程序集,您可以创建Roslyn metadatreference,如下所示:

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();

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