2014-11-08 2 views
5

В качестве входных данных для компиляции У меня есть строка со следующим кодом в нем:Как вы добавляете ссылки на типы, скомпилированные в потоке памяти, используя Roslyn?

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
    public string EmailAddress { get; set; } 
} 

У меня есть следующий код, обратите внимание на комментарий в [01]. Цель здесь взять строку, содержащую класс (от this.Source и испускают код для сборки в MemoryStream

var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location); 
var assemblyName = Guid.NewGuid().ToString(); 
var syntaxTrees = CSharpSyntaxTree.ParseText(this.Source); 

// build references up 
var references = new List<MetadataReference>(); 
//[01] references.Add("System.dll")); 

// set up compilation 
var compilation = CSharpCompilation.Create(assemblyName) 
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) 
    .AddReferences(references) 
    .AddSyntaxTrees(syntaxTrees); 

// build the assembly 
Assembly assembly; 
using (var stream = new MemoryStream()) 
{ 
    // this is broked... 
    EmitResult compileResult = compilation.Emit(stream); 
    // [02] we get here, with diagnostic errors (check compileResult.Diagnostics) 
    assembly = Assembly.Load(stream.GetBuffer()); 
} 

В [02] я получаю BadImageFormat исключение, следующее в compileResult.Diagnostics.:

[0]: warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. 
[1]: (2,18): error CS0518: Predefined type 'System.Object' is not defined or imported 
[2]: (4,16): error CS0518: Predefined type 'System.String' is not defined or imported 
[3]: (4,40): error CS0518: Predefined type 'System.Void' is not defined or imported 
[4]: (5,16): error CS0518: Predefined type 'System.String' is not defined or imported 
[5]: (5,39): error CS0518: Predefined type 'System.Void' is not defined or imported 
[6]: (6,16): error CS0518: Predefined type 'System.Int32' is not defined or imported 
[7]: (6,31): error CS0518: Predefined type 'System.Void' is not defined or imported 
[8]: (7,16): error CS0518: Predefined type 'System.String' is not defined or imported 
[9]: (7,43): error CS0518: Predefined type 'System.Void' is not defined or imported 
[10]: (2,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments 

Если добавить using System; в начале кода я получаю следующее сообщение об ошибке:

error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?) 

Это заставляет меня поверить, что у меня нет доступа к Системе, откуда я сижу, и именно поэтому я заштриховал в этом псевдокоде references.Add("System.dll"));. Это явно неверно, но это мое намерение.

Для получения дополнительной информации целью здесь является создание экземпляра сгенерированного типа динамически и назначение значений свойствам.

Каков правильный способ сделать ссылки доступными для компилятора?

Или, есть ли другой подход для компиляции класса, подобного этому (из ввода строки)?

+0

Какую версию рослина вы используете? – davidfowl

ответ

4

Позвоните по номеру AssemblyMetadata.CreateFromFile(path) method и пройдите typeof(object).Assembly.Location (или другие сборки).

+0

Обратите внимание, что объект и друзья обычно приходят из mscorlib.all или System.Runtime.dll, а не из System.dll. –

+0

Это все еще верно для ядра asp.net? – jasdefer

+0

CSharpCompilation (то есть сообщает о диагностике) хочет MetadataReference []. Где вы хотите назвать этот AssemblyMetadata в приведенном выше коде? – StingyJack

0

Вы можете использовать эту технику, чтобы получить полный путь к сборке

var assemblyFullPath = typeof(object).Assembly.Location); 

так что вы можете в конечном итоге с этим:

references.Add(new MetadataFileReference(typeof(object).Assembly.Location))); 

UPDATE

Вы можете попробовать использовать :

PortableExecutableReference MetadataReference.CreateFromImage(
     ImmutableArray<byte> peImage, 
     MetadataReferenceProperties properties = default(MetadataReferenceProperties), 
     DocumentationProvider documentation = null, 
     string filePath = null) 
+0

Спасибо @ Гамлет-Акопян. К сожалению, «MetadataFileReference» кажется помеченным как внутренним, так и недоступным из-за его уровня защиты. – MisterJames

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

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