2016-11-08 6 views
5

Я улучшаю существующий процесс с генерацией кода времени выполнения. Код, который я создаю во время выполнения, требует доступа к некоторым из тех же DLL, что процесс, создающий код, уже ссылается.Как я могу загрузить загруженную сборку в рабочее пространство Roslyn в C#

Проблема заключается в том, что процесс выполняется внутри стороннего программного обеспечения, которое загружает 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() является устаревшим методом, который делает внутри: строка location = CorLightup.Desktop.GetAssemblyLocation (сборка); Затем загружается из файла. Так что это то же самое, что работать с CreateFromFile() .. то есть не работает в моем случае. Я просто положил его туда как пример того, чего бы я хотел :) – Wizbit

ответ

1

Для управляемой сборки, загруженной с помощью Assembly.Load (байт []) вы можете создать 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(); 

Обратите внимание, что это не работает для сборок, загруженных из файла, так как макет в памяти отличается.

+0

Отличное решение для кода, зависящего от платформы. Есть ли возможность сделать то же самое с использованием .NET Standard 2.0? Я использую roslyn в таком контексте. – Benni

 Смежные вопросы

  • Нет связанных вопросов^_^