Best practice to write highly user extendable C# application

后端 未结 1 369
执念已碎
执念已碎 2020-12-19 19:12

I am currently at a research institute that does micromaching/fine mechanics and was asked to develop a controller software for the current setup we use in one of our labs.

1条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-19 19:47

    I did this 'script' thing using the .NET integrated C# compiler.
    It is some work to do but basically is looks like this:

        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;
        }
    

    The real code does a lot more things, including a code editor.
    It works very well for years now in our factory.

    This way the users use C# for the scripts and can therefore use the same API as you do.

    You can use a code template that looks like a plain .cs file. It is build at runtime and provided to the source parameter of Compile.

    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) { /* ... */ }
        }
    }
    

    Example:

    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");
    

    0 讨论(0)
提交回复
热议问题