即时添加新的cs文件以加载我正在运行的应用程序?

Gua*_*apo 3 .net c#

我有一个命令处理程序,基本上这样工作:

ControlList.Handlers[CommandType.MyCommandComesHere].Handle(data);
Run Code Online (Sandbox Code Playgroud)

Handlers是一个Dictionary<CommandType, ICommandHandler>并且CommandType是一个枚举.

Handle 轮流将导致它:

using System;
using log4net;

namespace My_Application
{
    public class MyCommand : ICommandHandler
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(MyCommand));

        public void Handle(Events data)
        {
            Console.WriteLine("I can load cs files on the fly yay!!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是如何才能使我的应用程序编译并让我在运行时使用该cs文件?

任何简单的例子都会非常受欢迎,但不是必需的,只要我能得到一些关于我需要寻找什么的指示,因为我甚至不确定我需要做些什么来实现这一点.

为了简单起见,我目前正在尝试理解如何将cs文件加载到已经编译并且当前正在运行的应用程序中.

The*_*kis 5

使用CodeDOM,您需要首先创建一个编译器提供程序.(您可能需要设置GenerateExecutablefalseGenerateInMemorytrue你的目的.)

    var csc = new CSharpCodeProvider();
    var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true);
    parameters.GenerateExecutable = false;
    parameters.GenerateInMemory = true;
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用编译程序集CompileAssemblyFromSource并从中CompilerResults返回.从此返回的对象中,使用其CompiledAssembly属性获取对生成的程序集的引用.

    var results = csc.CompileAssemblyFromSource(parameters, "contents of the .cs file");
    var assembly = results.CompiledAssembly;
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用反射从该程序集创建实例并在其上调用方法.

    var instance = assembly.CreateInstance("MyCommand");
    // etc...
Run Code Online (Sandbox Code Playgroud)

或者,如果您只对短代码片段感兴趣,那么使用Roslyn可能是值得的.你需要创建ScriptEngine第一个.

var engine = new ScriptEngine();
Run Code Online (Sandbox Code Playgroud)

然后你就可以Execute在它上面添加字符串 - 或者Execute<T>如果你确信字符串中的表达式返回一个可赋值的类型T.

var myObject = engine.Execute("1+1");
var myInt = engine.Execute<int>("1+1");
Run Code Online (Sandbox Code Playgroud)

它肯定更直接,所以值得研究它是否符合您的目的.