如何从 .cs 文件加载类并在代码中使用它

Ber*_*tar 0 .net c# vb.net compilation

我想从 .cs 文件加载一个类并在另一个代码中使用它。
假设我有一个.cs文件,其中包含这样的代码:

//some imports

public class Commands
{

     //a lot of commands

}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用 CSharpCodeProvider 或其他方法从文件加载此类并创建命令列表。

来自控制台应用程序的一段代码。

list<Commands> lst;
Run Code Online (Sandbox Code Playgroud)

问题是如何动态加载命令类(在运行时)(无需重新启动控制台应用程序或启动 VS)并创建命令列表?

Xar*_*ugh 5

试试这个例子,我把它放在一起并测试过:

构建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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在输出目录 (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)");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后运行第一个控制台应用程序并观察它的输出。它应该记录“Hello (Command)”,表明代码已正确编译、加载和执行。

该示例显示了如何CodeDom.Compiler在运行时使用编译 cs 文件,然后将其作为 dll 加载以在其中运行代码。请注意,几乎没有实现错误处理。

这应该可以回答这个问题,但可能仍然有更好的方法来处理您的用例。在插件加载的情况下,使用作为对两个程序集的引用添加的接口以避免使用反射等是有意义的。