2016-06-22 5 views
3

У меня возникла проблема при компиляции текста в динамические объекты во время выполнения.C# Загрузка сборок динамически

Я написал простой кусок кода, чтобы составить текст:

public class CompileFactory 
{ 
    public dynamic Compile(String classCode, String mainClass, Object[] requiredAssemblies) 
    { 
     CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> 
      { 
      { "CompilerVersion", "v4.0" } 
      }); 

     CompilerParameters parameters = new CompilerParameters 
     { 
      GenerateExecutable = true,  // Create a dll 
      GenerateInMemory = true,   // Create it in memory 
      WarningLevel = 3,     // Default warning level 
      CompilerOptions = "/optimize", // Optimize code 
      TreatWarningsAsErrors = false  // Better be false to avoid break in warnings 
     }; 

     // Add all extra assemblies required 
     foreach (var extraAsm in requiredAssemblies) 
     { 
      parameters.ReferencedAssemblies.Add(extraAsm as string); 
     } 
     CompilerResults results = provider.CompileAssemblyFromSource(parameters, classCode); 
     if (results.Errors.Count != 0) 
     { 
      return "FAILED"; 
     } 
     return results.CompiledAssembly.CreateInstance(mainClass); ; 
    } 
} 

Это, как я использую метод Compile.

List<string> assemblies = new List<string>{"System.Net.Mail.dll", "System.Net.dll"}; 
dynamic obj = compile.Compile(fileText, pluginName, assemblies.ToArray()); 

Как вы можете видеть, я добавляю ссылки на дополнительные сборки в какой-то момент. По какой-то причине, когда я добавляю using System.Net; в текстовый файл, он не будет ссылаться и я получаю ошибки. Текст, который я компилирую, буквально является файлом .cs, сохраненным как текст. Я думал об этом, извлекая using * и добавляя их отдельно, однако при добавлении System.Net.Mail.dll файл метаданных не найден.

Кто-нибудь испытал что-то подобное? Я действительно хотел бы добавить файл using * в файл и быть готовым к нему. Любой вход был бы оценен.

+0

Можете ли вы показать, как вы называете 'Compile'? Я хотел бы видеть аргументы, которые вы передаете –

+0

@ PhilippeParé 'dynamic obj = compile.Compile (fileText, pluginName, assemblylies.ToArray());' Assemblies - это просто 'List {" System.Net.Mail.dll " , «System.Net.dll»}; ' –

+0

Вы должны добавить это в свой пост, потому что это очень важно для вашей проблемы, см. Мой ответ ниже –

ответ

2

Проблема здесь в том, что System.Net.dll не существует. Вы можете проверить, в какой сборке есть тип .Net, щелкнув правой кнопкой мыши по ссылке, и выберите «Перейти к определению». Это вызовет вкладку с определением класса «из метаданных». В верхней части этого файла у вас есть #region, показывающий, откуда этот тип. В случае TcpClient, мы можем увидеть это:

#region Assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.dll 
#endregion 

Изменить вызов Compile с «System.dll» вместо «System.Net.dll» и он должен работать только штрафом

Редактировать/Уточнение. Невозможно получить имя сборки из инструкции using.

+0

Конечно, это сработает для этого примера. Я хотел бы получить решение, в котором будет разрешен любой тип ссылки на сборку. Когда добавление 'System.dll' к ссылкам,' System.XML.dll' не добавляется. Вы добираетесь туда, куда я иду? Решите на основе 'использования *' вызовов, которые дополнительные сборки должны быть добавлены при компиляции. –

+0

Рядом с этим 'System.Net.dll' загружается только штраф,' System.Net.Mail.dll', однако, не –

+1

, вы не можете найти сборку, требуемую только на основе инструкции 'using'. Я рекомендую вам поставить все необходимые вам сборки в ссылках –