如何从.cs文件加载类并在代码中使用它 [英] How to load a class from .cs file and use it in code

查看:49
本文介绍了如何从.cs文件加载类并在代码中使用它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从.cs文件中加载类,并在其他代码中使用它.
假设我有一个 .cs 文件,其中包含如下代码:

I want to load a class form a .cs file and use it in another code.
Assume I have a .cs file which contains code like that:

//some imports

public class Commands
{

     //a lot of commands

}

我正在尝试的是使用CSharpCodeProvider或其他工具从文件中加载此类,并创建命令列表.

What I am trying is to load this class from a file using CSharpCodeProvider or whatever and create a list of Commands.

控制台应用程序中的一段代码.

A piece of code from a console app.

list<Commands> lst;

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

The question is how can I load Commands class dynamically (at runtime) (without restarting the console app or starting VS) and create the list of Commands?

推荐答案

尝试以下示例,我将其组合在一起并进行了测试:

Try this example, which I have put together and tested:

program.cs 构建为 .Net Framework Console App ,例如Visual Studio.

Build program.cs as a .Net Framework Console App in e.g. 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 的文本文件,其内容如下:

In the output directory (bin), next to the console app executable place a text file named mySource.cs with this content:

// 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(命令)",表明代码已正确编译,加载和执行.

Then run the first console app and observe it's output. It should log "Hello (Command)", showing that the code was correctly compiled, loaded and executed.

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

The example shows how to use the CodeDom.Compiler to compile a cs-file at runtime and then load it as dll to run code within it. Be aware, that almost no error handling was implemented.

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

This should answer the question, but there may still be better approaches to handling your use-case. In case of plugin loading it makes sense to use interfaces which are added as a reference to both assemblies to avoid the use of reflection, etc.

这篇关于如何从.cs文件加载类并在代码中使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆