Попробуйте этот пример, который я собрал и протестировал:
Построить program.cs как .Net Framework Console App
, например, в Visual Studio.
// program.cs
using System;
using System.IO;
using System.CodeDom.Compiler;
using System.Reflection;
namespace RuntimeCompile
{
class Program
{
static void Main(string[] args)
{
// Get a path to the file(s) to compile.
FileInfo sourceFile = new FileInfo("mySource.cs");
Console.WriteLine("Loading file: " + sourceFile.Exists);
// Prepary a file path for the compiled library.
string outputName = string.Format(@"{0}\{1}.dll",
Environment.CurrentDirectory,
Path.GetFileNameWithoutExtension(sourceFile.Name));
// Compile the code as a dynamic-link library.
bool success = Compile(sourceFile, new CompilerParameters()
{
GenerateExecutable = false, // compile as library (dll)
OutputAssembly = outputName,
GenerateInMemory = false, // as a physical file
});
if (success)
{
// Load the compiled library.
Assembly assembly = Assembly.LoadFrom(outputName);
// Now, since we didn't have reference to the library when building
// the RuntimeCompile program, we can use reflection to create
// and use the dynamically created objects.
Type commandType = assembly.GetType("Command");
// Create an instance of the loaded class from its type information.
object commandInstance = Activator.CreateInstance(commandType);
// Invoke the method by name.
MethodInfo sayHelloMethod = commandType.GetMethod("SayHello", BindingFlags.Public | BindingFlags.Instance);
sayHelloMethod.Invoke(commandInstance, null); // no arguments, no return type
}
Console.WriteLine("Press any key to exit...");
Console.Read();
}
private static bool Compile(FileInfo sourceFile, CompilerParameters options)
{
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFile.FullName);
if (results.Errors.Count > 0)
{
Console.WriteLine("Errors building {0} into {1}", sourceFile.Name, results.PathToAssembly);
foreach (CompilerError error in results.Errors)
{
Console.WriteLine(" {0}", error.ToString());
Console.WriteLine();
}
return false;
}
else
{
Console.WriteLine("Source {0} built into {1} successfully.", sourceFile.Name, results.PathToAssembly);
return true;
}
}
}
}
В выходном каталоге (bin) рядом с исполняемым файлом консольного приложения поместите текстовый файл с именем mySource.cs со следующим содержимым:
// mySource.cs
using System;
internal class Program
{
static void Main()
{
Console.WriteLine("Hello from mySource!");
Console.ReadLine();
}
}
public class Command
{
public void SayHello()
{
Console.WriteLine("Hello (Command)");
}
}
Затем запустите первое консольное приложение и просмотрите еговыход.Должно появиться сообщение «Hello (Command)», показывающее, что код был правильно скомпилирован, загружен и выполнен.
В примере показано, как использовать CodeDom.Compiler
для компиляции cs-файла во время выполнения, а затем загрузить его.как DLL для запуска кода внутри него.Имейте в виду, что обработка ошибок почти не была реализована.
Это должно ответить на вопрос, но, тем не менее, могут быть более эффективные подходы к обработке вашего варианта использования.В случае загрузки плагина имеет смысл использовать интерфейсы, которые добавляются в качестве ссылки на обе сборки, чтобы избежать использования отражения и т. Д.