2016-11-08 56 views
5

我正在使用運行時代碼生成來增強現有的進程。我在運行時創建的代碼需要訪問一些與創建代碼的進程已經引用相同的dll。我如何將加載的程序集餵給C#中的Roslyn工作區?

問題是該進程在某些第三方軟件中運行,該軟件從資源加載dll並將它們注入到我的進程中......因此,我無法訪問磁盤上的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); 

有什麼建議?

+0

所以你已經有一個對某個地方的組裝對象的引用,對吧?將它傳遞給'MetadataReference.CreateFromAssembly()'會發生什麼? – Ties

+1

@Ties:只有從文件加載時纔有效。 http://source.roslyn.io/#Microsoft.CodeAnalysis/MetadataReference/MetadataReference.cs,324 – SLaks

+0

@Ties:根據Slaks評論;如果你看看他的鏈接,CreateFromAssembly()是一個內部不贊成的方法: string location = CorLightup.Desktop.GetAssemblyLocation(assembly); 然後從文件加載。所以它就像運行CreateFromFile()一樣。即在我的情況下不起作用。我只是把它放在那裏作爲我希望我的一個例子:) – Wizbit

回答

1

對於使用Assembly.Load(字節[])你可以創建一個羅斯林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(); 

注意,這並不從一個文件中加載的程序集工作,因爲內存中的佈局是不同的。

+0

平臺相關代碼的絕佳解決方案。有沒有可能性使用.NET標準2.0來做同樣的事情?我在這種情況下使用roslyn。 – Benni

相關問題