2012-05-25 5 views
7

Я генерирую Greeter.dll с использованием компилятора Roslyn. Моя проблема возникает при загрузке DLL-файла.Загрузка сборки, сгенерированной компилятором Roslyn

Вот код:

сообщение
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 
} 

Ошибка возникает на линии assembly = Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), @"Greeter.dll")); и читает

Im Modul Würde Эйн Assemblymanifest erwartet. (Ausnahme фон HRESULT: 0x80131018)

что примерно переводится

манифеста сборки, как ожидается, в модуле.

Кто-нибудь знает, что мне не хватает здесь?

+0

у вас есть несколько ошибок в коде. Видимо, вы уже разобрались в них (но для них не было PDB). В следующий раз посмотрите на 'result.Diagnostics', чтобы выяснить, в чем проблема. – svick

ответ

0

Я добавляла поддержку Roslyn к O2 Plarform и вот как вы можете использовать его поддержку Roslyn компилировать (код), создание (и монтаж) и вызывать (его метод) одна строка кода:

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 

Вот версия, которая выполняет фрагмент кода, который выглядит, как ваша (я добавил возвращаемое значение):

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 

еще пару деталей и скриншотов, как это выглядит, посмотреть в блоге: 1 line to compile, create and execute: O2 Script to use Roslyn to Dynamically compile and execute a method

UPDATE: см http://blog.diniscruz.com/search/label/Roslyn для большого числа числа связанных Рослин сообщений и инструментов (создано используя платформу O2)

-1

Оказывается, мне нужно было создать файл 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

Это не проблема в вашем коде. – svick

0

Этот код работает прекрасно:

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

Просто кусок кода без объяснений не очень полезен. Означает ли это, что вы решили свою проблему? Или это должно быть просто расширением вопроса? – svick

+0

Обратите внимание, что в CompilationsOptions AssemblyKind был переименован в: OutputKind.DynamicallyLinkedLibrary –

+0

. Для справки одной из проблем с исходным кодом было не определение OutputKind (поскольку одной из ошибок был необходимость использования статического метода Main) –

13

Я наткнулся на это и, хотя у вас есть принятый ответ, я не думаю, что это полезно вообще. Поэтому я просто оставлю это здесь для будущих искателей, таких как я.

Проблема с кодом две вещи, которые вы бы выяснили, глядя на возвращаемого значения из

EmitResult result = compilation.Emit(file); 

Если вы посмотрите на свойства на объекте EmitResult, вы бы обнаружили, что там были 2 ошибки в результатах. Член диагноза.

  1. Основной метод не нашел
  2. Не удалось найти класс консоли

Таким образом, чтобы решить эту проблему, 1. Вы должны пометить результат в виде DLL 2.Вам нужно добавить 'using System;' к коду вы передаете в API или сказать «System.Console.WriteLine»

Следующий код работает вносить изменения, чтобы исправить эти две проблемы:

 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

Существует новый API для References который выглядит следующим образом:

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) 
); 

Это с последним в сентябре Рослин-CTP 2012 ...

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

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