2014-11-08 32 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

您使用的是什么版本的roslyn? – davidfowl 2014-11-08 22:45:07

回答

4

致电AssemblyMetadata.CreateFromFile(path) method,并通过typeof(object).Assembly.Location(或其他组件)。

+0

请注意,对象和朋友通常来自mscorlib.all或System.Runtime.dll,而不是System.dll。 – 2014-11-08 23:31:30

+0

对于asp.net核心,这仍然是真的吗? – jasdefer 2016-10-11 16:49:55

+0

CSharpCompilation(即报告诊断)需要MetadataReference []。在上面的代码中,你打算在什么地方调用AssemblyMetadata? – StingyJack 2017-02-25 13:51:56

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

谢谢@ Hamlet-Hakobyan。不幸的是,'MetadataFileReference'由于其保护级别而被标记为内部且不可访问。 – MisterJames 2014-11-08 22:42:16