2012-05-25 15 views
7

Generuję Greeter.dll przy użyciu kompilatora Roslyn. Mój problem występuje podczas próby załadowania pliku DLL.Ładowanie zespołu generowanego przez kompilator Roslyn

Oto kod:

wiadomość
using System; 

using Roslyn.Compilers; 
using Roslyn.Compilers.CSharp; 

using System.IO; 
using System.Reflection; 
using System.Linq; 

namespace LoadingAClass 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var syntaxTree = SyntaxTree.ParseCompilationUnit(@" 
class Greeter 
{ 
    static void Greet() 
    { 
     Console.WriteLine(""Hello, World""); 
    } 
}"); 

      var compilation = Compilation.Create("Greeter.dll", 
       syntaxTrees: new[] { syntaxTree }, 
       references: new[] { 
        new AssemblyFileReference(typeof(object).Assembly.Location), 
        new AssemblyFileReference(typeof(Enumerable).Assembly.Location), 
       }); 

      Assembly assembly; 
      using (var file = new FileStream("Greeter.dll", FileMode.Create)) 
      { 
       EmitResult result = compilation.Emit(file); 
      } 

      assembly = Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), @"Greeter.dll")); 
      Type type = assembly.GetType("Greeter"); 
      var obj = Activator.CreateInstance(type); 

      type.InvokeMember("Greet", 
       BindingFlags.Default | BindingFlags.InvokeMethod, 
       null, 
       obj, 
       null); 

      Console.WriteLine("<ENTER> to continue"); 
      Console.ReadLine(); 

     } 
    } 
    // Thanks, http://blogs.msdn.com/b/csharpfaq/archive/2011/11/23/using-the-roslyn-symbol-api.aspx 
} 

Błąd występuje na linii assembly = Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), @"Greeter.dll")); i czyta

Im Modul wurde ein Assemblymanifest erwartet. (Ausnahme von HRESULT: 0x80131018)

czego około przekłada się

manifeście zespół oczekiwano w module.

Czy ktoś wie, czego tu brakuje?

+0

masz kilka błędów w kodzie. Najwyraźniej już je wymyśliłeś (ale nie było wśród nich PDB). Następnym razem spójrz na 'result.Diagnostics', aby dowiedzieć się, jaki jest problem. – svick

Odpowiedz

0

I zostały dodanie wsparcia Roslyn do O2 Plarform i tutaj jest jak można wykorzystać swoje poparcie Roslyn skompilować (kod), tworzenie (i montaż) oraz powołać (jego metoda) jedna linia kodu:

return @"using System; class Greeter { static string Greet() { return ""Another hello!!""; }}" 
     .tree().compiler("Great").create_Assembly().type("Greeter").invokeStatic("Greet"); 

//O2Ref:O2_FluentSharp_Roslyn.dll 

Oto wersja, która wykonuje fragment kodu, który wygląda jak twoja (I dodaje wartości zwracanej):

panel.clear().add_ConsoleOut(); 
var code = @" 
using System; 
class Greeter 
{ 
    static string Greet() 
    { 
     Console.WriteLine(""Hello, World""); 
     return ""hello from here""; 
    } 
}"; 
var tree = code.astTree(); 
if (tree.hasErrors()) 
    return tree.errors(); 

var compiler = tree.compiler("Great") 
        .add_Reference("mscorlib"); 

if (compiler.hasErrors()) 
    return compiler.errors();  

var assembly =tree.compiler("Great") 
        .create_Assembly(); 

return assembly.type("Greeter") 
       .invokeStatic("Greet"); 

//O2Ref:O2_FluentSharp_Roslyn.dll 
//O2File:_Extra_methods_Roslyn_API.cs 
//O2File:API_ConsoleOut.cs 

na kilka więcej szczegółów i zrzuty ekranu jak to wygląda, zobacz ten post na blogu: 1 line to compile, create and execute: O2 Script to use Roslyn to Dynamically compile and execute a method

UPDATE: zobaczyć http://blog.diniscruz.com/search/label/Roslyn dla dużej liczby numerów z Roslyn związanych stanowisk i narzędzi (utworzony przy użyciu platformy O2)

-1

Okazuje się, że potrzebowałem stworzyć plik pdb.

using (FileStream dllStream = new FileStream(dllPath, FileMode.OpenOrCreate)) 
using (FileStream pdbStream = new FileStream(pdbPath, FileMode.OpenOrCreate)) 
{ 
    result = compilation.Emit(
     executableStream: dllStream, 
     pdbFileName: pdbPath, 
     pdbStream: pdbStream); 
} 
+0

To nie jest problem w twoim kodzie. – svick

0

Ten kod pracował pięknie:

using System; 

using Roslyn.Compilers; 
using Roslyn.Compilers.CSharp; 

using System.IO; 
using System.Reflection; 
using System.Linq; 

namespace LoadingAClass 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var syntaxTree = SyntaxTree.ParseCompilationUnit(@" 
using System; 
namespace HelloWorld 
{ 
    class Greeter 
    { 
     public static void Greet() 
     { 
      Console.WriteLine(""Hello, World""); 
     } 
    } 
}"); 

      string dllPath = Path.Combine(Directory.GetCurrentDirectory(), "Greeter.dll"); 
      string pdbPath = Path.Combine(Directory.GetCurrentDirectory(), "Greeter.pdb"); 

      var compilation = Compilation.Create(dllPath, 
       new CompilationOptions(
        assemblyKind: AssemblyKind.DynamicallyLinkedLibrary 
       )) 
       .AddSyntaxTrees(syntaxTree) 
       .AddReferences(new AssemblyFileReference(typeof(object).Assembly.Location)) 
       .AddReferences(new AssemblyFileReference(typeof(Enumerable).Assembly.Location)); 

      EmitResult result; 

      using (FileStream dllStream = new FileStream(dllPath, FileMode.OpenOrCreate)) 
      using (FileStream pdbStream = new FileStream(pdbPath, FileMode.OpenOrCreate)) 
      { 
       result = compilation.Emit(
        executableStream: dllStream, 
        pdbFileName: pdbPath, 
        pdbStream: pdbStream); 
      } 

      if (result.Success) 
      { 
       //assembly = Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), @"Greeter.dll")); 
       Assembly assembly = Assembly.LoadFrom(@"Greeter.dll"); 

       Type type = assembly.GetType("HelloWorld.Greeter"); 
       var obj = Activator.CreateInstance(type); 

       type.InvokeMember("Greet", 
        BindingFlags.Default | BindingFlags.InvokeMethod, 
        null, 
        obj, 
        null); 
      } 
      else 
      { 
       Console.WriteLine("No Go"); 
       Console.WriteLine(result.Diagnostics.ToString()); 
      } 

      Console.WriteLine("<ENTER> to continue"); 
      Console.ReadLine(); 

     } 
    } 
    // Thanks, http://blogs.msdn.com/b/csharpfaq/archive/2011/11/23/using-the-roslyn-symbol-api.aspx 
    // Thanks, http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/d620a4a1-3a90-401b-b946-bfa1fc6ad7a2 
} 
+2

Tylko kawałek kodu bez wyjaśnienia nie jest zbyt użyteczny. Czy to oznacza, że ​​rozwiązałeś swój problem? Czy to ma być tylko przedłużenie tego pytania? – svick

+0

Należy zauważyć, że w CompilationsOptions nazwa AssemblyKind została zmieniona na: OutputKind.DynamicallyLinkedLibrary –

+0

Dla odniesienia, jednym z problemów z oryginalnym kodem była nie definicja OutputKind (ponieważ jednym z błędów była potrzeba statycznej metody Main) –

13

Natknąłem się na to i mimo, że masz akceptowaną odpowiedź, nie sądzę, że jest to pomocne w ogóle. Tak, zostawię to tutaj dla przyszłych poszukiwaczy takich jak ja.

Problem z kodem to dwie rzeczy, które zostały znalezione przez patrząc na zwróconej wartości od

EmitResult result = compilation.Emit(file); 

Jeśli spojrzeć na właściwości w obiekcie EmitResult, byś stwierdził, że nie były 2 błędy w elemencie results.Diagnostics.

  1. metoda Main Nie znaleziono
  2. Nie można odnaleźć klasy Console

Tak więc, aby rozwiązać ten problem, 1. Trzeba zaznaczyć wyjście jako DLL 2.Musisz dodać "za pomocą systemu"; do kodu jesteś przechodząc do API lub powiedzieć „System.Console.WriteLine”

Następujący kod działa dokonywania zmian, aby rozwiązać te dwa problemy:

 var outputFile = "Greeter.dll"; 
     var syntaxTree = SyntaxTree.ParseCompilationUnit(@" 
// ADDED THE FOLLOWING LINE 
using System; 

class Greeter 
{ 
    public void Greet() 
    { 
     Console.WriteLine(""Hello, World""); 
    } 
}"); 
     var compilation = Compilation.Create(outputFile, 
      syntaxTrees: new[] { syntaxTree }, 
      references: new[] { 
       new AssemblyFileReference(typeof(object).Assembly.Location), 
       new AssemblyFileReference(typeof(Enumerable).Assembly.Location), 
      }, 

// ADDED THE FOLLOWING LINE 
      options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary)); 

     using (var file = new FileStream(outputFile, FileMode.Create)) 
     { 
      EmitResult result = compilation.Emit(file); 
     } 

     Assembly assembly = Assembly.LoadFrom("Greeter.dll"); 

     Type type = assembly.GetType("Greeter"); 
     var obj = Activator.CreateInstance(type); 

     type.InvokeMember("Greet", 
      BindingFlags.Default | BindingFlags.InvokeMethod, 
      null, 
      obj, 
      null); 

     Console.WriteLine("<ENTER> to continue"); 
     Console.ReadLine(); 
0

Jest nowy API dla Odsyłacze który wygląda tak:

var compilation = Compilation.Create(outputFile, 
    syntaxTrees: new[] { syntaxTree }, 
    references: new[] { 
     new MetadataFileReference(typeof(object).Assembly.Location), 
     new MetadataFileReference(typeof(Enumerable).Assembly.Location), 
    }, 
    options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary) 
); 

to z najnowszymi Roslyn-CTP 2012 w Sept ...

Powiązane problemy