2016-11-08 41 views
5

Ulepszam istniejący proces z generowaniem kodu środowiska wykonawczego. Kod, który tworzę w czasie wykonywania, wymaga dostępu do niektórych z tych samych bibliotek dll, które proces tworzenia kodu już odwołuje.Jak mogę załadować załadowany zespół do przestrzeni roboczej Roslyn w C#

Problem polega na tym, że proces działa w obrębie jakiegoś oprogramowania innej firmy, które ładuje biblioteki dll z zasobów i wstrzykuje je do mojego procesu ... w ten sposób nie mam dostępu do biblioteki DLL na dysku ani do zasobu zawierającego bibliotekę dll zewnętrzne opakowanie.

W rezultacie staram się wykorzystać zgromadzenia, które już mam w pamięci i wprowadzić je do przestrzeni roboczej Roslyn, w której umieszczam kod środowiska wykonawczego do kompilacji. Myślałem, że mogę spróbować szeregowania Zgromadzenie z binarnym formater, jak na to SO: Opposite operation to Assembly Load(byte[] rawAssembly)

Ale nawet jeśli dość dużo wziąć kod jak:

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

uzyskać:

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

Żadne z pozostałych wyników wyszukiwania nie wydawało się lepsze.

Co chcę zrobić coś jak:

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

jakieś sugestie?

+0

Masz już gdzieś odniesienie do obiektu zespołu, prawda? Co stanie się, gdy przekażesz to do 'MetadataReference.CreateFromAssembly()'? – Ties

+1

@Ties: Działa tylko wtedy, gdy został załadowany z pliku. http://source.roslyn.io/#Microsoft.CodeAnalysis/MetadataReference/MetadataReference.cs,324 – SLaks

+0

@Ties: Zgodnie z komentarzem Slaks; jeśli spojrzysz na jego łącze, CreateFromAssembly() jest nieaktualną metodą wewnętrznie: string string = CorLightup.Desktop.GetAssemblyLocation (assembly); Następnie ładuje z pliku. Tak samo działa funkcja CreateFromFile(), np. Nie działa w moim przypadku. Po prostu umieściłem to jako przykład tego, co chciałbym mieć :) – Wizbit

Odpowiedz

1

Na zarządzanym zespole załadowane stosując Assembly.Load (byte []) można utworzyć Roslyn MetadataReference tak:

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

Zauważ, że to nie działa dla zespołów ładowane z pliku, ponieważ układ w pamięci jest inny.

+0

Doskonałe rozwiązanie dla kodu zależnego od platformy. Czy istnieje możliwość robienia tego samego przy użyciu .NET Standard 2.0? Używam roslyn w takim kontekście. – Benni