2014-11-08 11 views
5

come input per la compilazione Ho uno stringa con il seguente codice in esso:Come si aggiungono riferimenti a tipi compilati in un flusso di memoria utilizzando Roslyn?

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

ho il seguente codice, si noti il ​​commento a [01]. L'intento è quello di prendere una stringa che contiene una classe (da this.Source ed emettere il codice per il montaggio in un 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()); 
} 

A [02] io sono sempre un'eccezione BadImageFormat, con quanto segue in 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 

Se posso aggiungere un using System; per l'inizio del codice ottengo il seguente errore:

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

Questo mi porta a credere che non ho accesso al Sistema da dove mi siedo, ed è per questo che ho soppresso lo pseudo-codice references.Add("System.dll"));. È ovviamente sbagliato, ma è il mio intento.

Per ulteriori informazioni, l'intento qui è quello di creare un'istanza del tipo generato in modo dinamico e assegnare valori alle proprietà.

Qual è il modo corretto per rendere i riferimenti disponibili per il compilatore?

Oppure, esiste un altro approccio per la compilazione di una classe come questa (da una stringa di input)?

+0

Quale versione di roslyn stai usando? – davidfowl

risposta

4

Chiamare lo AssemblyMetadata.CreateFromFile(path) method e passare typeof(object).Assembly.Location (o altri assiemi).

+0

Nota che oggetti e amici di solito provengono da mscorlib.all o System.Runtime.dll, non da System.dll. –

+0

È ancora vero per asp.net core? – jasdefer

+0

CSharpCompilation (che sta segnalando la diagnostica) richiede MetadataReference []. Dove intendi chiamare questo AssemblyMetadata nel codice sopra? – StingyJack

0

È possibile utilizzare questa tecnica per ottenere il percorso completo al gruppo

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

in modo da poter finire con questo:

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

UPDATE

Si può provare a utilizzare :

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

Grazie @ Hamlet-Hakobyan. Sfortunatamente 'MetadataFileReference' sembra contrassegnato come interno e inaccessibile a causa del suo livello di protezione. – MisterJames

Problemi correlati