c# - 编写高度用户可扩展的 C# 应用程序的最佳实践

标签 c# winforms plugins

我目前在一家从事微加工/精密机械的研究机构工作,并被要求为我们在一个实验室中使用的当前设置开发一个 Controller 软件。

我们有一个纳米级和一些其他设备,如百叶窗和滤光轮,它们应该由中央应用程序控制。该软件提供用于执行的预配置作业,这些作业基本上是为平台生成命令的算法,用于通过激光将不同的图案写入 sample (例如矩形、圆柱体等)

现在,如果能提供某种可能性来在运行时扩展此预定义作业列表,那就太好了,这意味着用户可以添加与提供的算法类似的算法。

我是 C# 新手(一般来说也是桌面应用程序新手),所以如果您能给我一些关于如何完成或我应该从哪里开始寻找的提示,我将非常感激。

最佳答案

我使用 .NET 集成 C# 编译器完成了这个“脚本”操作。
这是一些工作要做,但基本上是这样的:

    public Assembly Compile(string[] source, string[] references) {
        CodeDomProvider provider = new CSharpCodeProvider();
        CompilerParameters cp = new CompilerParameters(references);
        cp.GenerateExecutable = false;
        cp.GenerateInMemory = true;
        cp.TreatWarningsAsErrors = false;

        try {
            CompilerResults res = provider.CompileAssemblyFromSource(cp, source);
            // ...
            return res.Errors.Count == 0 ? res.CompiledAssembly : null;
        }
        catch (Exception ex) {
            // ...
            return null;
        }
    }

    public object Execute(Assembly a, string className, string methodName) {
        Type t = a.GetType(className);
        if (t == null) throw new Exception("Type not found!");
        MethodInfo method = t.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);          // Get method
        if (method == null) throw new Exception("Method '" + methodName + "' not found!");                                  // Method not found

        object instance =  Activator.CreateInstance(t, this);
        object ret = method.Invoke(instance, null); 
        return ret;
    }

真正的代码做了更多的事情,包括代码编辑器。
它在我们工厂多年来一直运行良好。

通过这种方式,用户可以使用 C# 编写脚本,因此可以使用与您相同的 API。

您可以使用看起来像普通 .cs 文件的代码模板。它在运行时构建并提供给 Compilesource 参数。

using System;
using System.IO;
using ...

namespace MyCompany.Stuff {
    public class ScriptClass {
        public object main() {

            // copy user code here
            // call your own methods here

        }

        // or copy user code here

        private int test(int x) { /* ... */ }
    }
}

示例:

string[] source = ??? // some code from TextBoxes, files or whatever, build with template file...
string[] references = new string[] { "A.dll", "B.dll" };

Assembly a = Compile(source, references);
object result = Execute(a, "MyCompany.Stuff.ScriptClass", "main");

关于c# - 编写高度用户可扩展的 C# 应用程序的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17723558/

相关文章:

c# - 常量值无法转换为 int

c++ - Qt Eclipse 集成和自定义小部件插件

api - 如何在gradle中列出 “apply from”脚本

c# - 将 IME 放在派生自 Control 的自定义文本框中

c# - 使用 --configuration 运行的 dotnet ef 导致 MSB4006

c# - Coinspot REST API - C#

java - 是否有用于添加 JBoss AS 6 支持的 NetBeans 插件?

c# - 尝试在 Visual Studio 中执行三个文本框的乘法

c# - GiveFeedback 事件未触发

c# - 如何在不实际下载文件的情况下判断 FTP 上的文件是否与本地文件相同?