2016-05-13 9 views
1

私は、動的に作成されたクラスの集合体を持っていますので、個別にコンパイルしたい(そしてコンパイルエラーを修正したい)。次に、それらを同じアセンブリに結合したいと思います。それらはすでにコンパイルされているので、(2回コンパイルするのを避けるために)構文木をアセンブリコンパイルに渡すだけではいけません。 それらをネットモジュールにコンパイルしようとしていたが、それらのネットモジュールをアセンブリへの参照として使用しようとしましたが、結果のアセンブリに必要な型がありません。ここでRoslynを使ってクラスを別々にコンパイルし、それらをアセンブリで一緒に組み合わせる

は、それがAとBへの参照を見つけることができないので(ロスリンのCompilationEmitTests.MultipleNetmodulesWithPrivateImplementationDetailsに非常によく似())私のテストコード

public static class Program 
{ 

    public static void Main() 
    { 
     var s1 = @"public class A {internal object o1 = new { hello = 1, world = 2 }; public static string M1() { return ""Hello, "";}}"; 
     var s2 = @"public class B : A{internal object o2 = new { hello = 1, world = 2 };public static string M2(){ return ""world!"";}}"; 
     var s3 = @"public class Program{public static void Main(){ System.Console.Write(A.M1()); System.Console.WriteLine(B.M2());}}"; 
     var comp1 = CreateCompilationWithMscorlib("a1", s1, compilerOptions: TestOptions.ReleaseModule); 
     var ref1 = comp1.EmitToImageReference(); 

     var comp2 = CreateCompilationWithMscorlib("a2", s2, compilerOptions: TestOptions.ReleaseModule, references: new[] { ref1 }); 
     var ref2 = comp2.EmitToImageReference(); 

     var comp3 = CreateCompilationWithMscorlib("a3", s3, compilerOptions: TestOptions.ReleaseExe.WithModuleName("C"), references: new[] { ref1, ref2 }); 

     var ref3 = comp3.EmitToImageReference(); 

     IEnumerable<byte> result = comp3.EmitToArray(); 

     Assembly assembly = Assembly.Load(result.ToArray()); 

     Module module = assembly.GetModule("C"); 

     Type prog = module.GetType("Program"); 

     object instance = Activator.CreateInstance(prog); 

     MethodInfo method = prog.GetMethod("Main"); 

     method.Invoke(null, null); 
    } 

    public static ImmutableArray<byte> ToImmutable(this MemoryStream stream) 
    { 
     return ImmutableArray.Create<byte>(stream.ToArray()); 
    } 

    internal static ImmutableArray<byte> EmitToArray 
    (
     this Compilation compilation, 
     EmitOptions options = null, 
     Stream pdbStream = null 
    ) 
    { 
     var stream = new MemoryStream(); 

     if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug) 
     { 
      pdbStream = new MemoryStream(); 
     } 

     var emitResult = compilation.Emit(
      peStream: stream, 
      pdbStream: pdbStream, 
      xmlDocumentationStream: null, 
      win32Resources: null, 
      manifestResources: null, 
      options: options); 

     return stream.ToImmutable(); 
    } 
    public static MetadataReference EmitToImageReference(
     this Compilation comp 
    ) 
    { 
     var image = comp.EmitToArray(); 
     if (comp.Options.OutputKind == OutputKind.NetModule) 
     { 
      return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.AssemblyName); 
     } 
     else 
     { 
      return AssemblyMetadata.CreateFromImage(image).GetReference(display: comp.AssemblyName); 
     } 
    } 

    private static CSharpCompilation CreateCompilationWithMscorlib(string assemblyName, string code, CSharpCompilationOptions compilerOptions = null, IEnumerable<MetadataReference> references = null) 
    { 
     SourceText sourceText = SourceText.From(code, Encoding.UTF8); 
     SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText, null, ""); 

     MetadataReference mscoreLibReference = AssemblyMetadata.CreateFromFile(typeof(string).Assembly.Location).GetReference(); 

     IEnumerable<MetadataReference> allReferences = new MetadataReference[] { mscoreLibReference }; 

     if (references != null) 
     { 
      allReferences = allReferences.Concat(references); 
     } 

     CSharpCompilation compilation = CSharpCompilation.Create 
     (
      assemblyName, 
      new[] {syntaxTree}, 
      options : compilerOptions, 
      references: allReferences 
     ); 

     return compilation; 
    } 

} 

メインは()静的メソッドを呼び出し()で例外がスローされていますクラス。

私は間違っていますか?

+0

スタックトレースをドロップすると役立つでしょう。 – muglio

+0

ダイナミックプログラム(文字列s3で定義)は、AとB(文字列s1とs2で定義されたネットモジュールにある)への参照を見つけることができません。ロザリン特有のものは何もありません。 –

+1

誰かが興味を持っている人は、こちらのソリューションをご覧ください:https://github.com/dotnet/roslyn/issues/11297。 – svick

答えて

0

ここでは、ユーザー0xd4dが同じ質問についてGithubに投稿した回答を示します。私はそれが動作することをテストした:

netmodulesはあなたがこれを行う必要はありません、ディスクにそれらすべてを保存した場合

assembly.LoadModule("a1.netmodule", a1_netmodule_bytes); 
assembly.LoadModule("a2.netmodule", a2_netmodule_bytes); 

をアクセスする必要がある前に、LoadModuleのを呼び出す必要があります。

私は彼がディスクに保存した場合、私はこれをする必要はないと述べたことは、まだ理解していません。

関連する問題