繁体   English   中英

带有内置交互式终端控制台(例如SublimeText,Visual Studio)的GUI应用程序的.NET参考设计

[英].NET reference design for GUI app with built-in interactive terminal console (e.g. SublimeText, Visual Studio)

我正在尝试构建一个具有交互式控制台的GUI应用程序,就像在SublimeText中找到的那样。 我希望这是一个有效的问题,因为它似乎是“软件开发所独有的实用,可回答的问题”。

简而言之,我看到在GUI应用程序中具有用于

  • 调试,在运行时探测内部变量
  • 测井
  • 快速配置更改

但是,我还没有遇到使用这种设计的任何现有开源应用程序。 我希望有人能做得到并且可以分享他/她的设计方法。

虽然我确实有一个在.NET中使用反射和调用的半工作解决方案,但它仅限于函数调用,而我无法探究嵌套的内部变量(例如object.property.property)。

为了使问题更具体,这些是我面临的问题:

  1. 不容易扩展(需要将每个新的GUI命令连接到控制台命令,反之亦然),是否有任何设计技巧? 路由命令(我也找不到有用的示例)?
  2. 如何执行可以访问整个.NET应用程序中所有现有对象实例的动态代码?

谢谢。

所以这是对我有用的代码:

namespace ReflectionsTest
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        //Events excluded

        private void ExecuteCommand(string command)
        {

                string cmd = "";
                cmd += @"using System;
                         using System.Collections.Generic;
                         using System.ComponentModel;
                         using System.Drawing;
                         using System.Text;
                         using System.Windows.Forms;
                         using System.Linq;
                         using Microsoft.CSharp;
                         using System.Reflection;
                         using ReflectionsTest;";
                         // i included a using statement for every namespace i want to adress direct
                cmd += @"namespace ReflectionConsole 
                        { 
                            public class RuntimeExecution 
                            { 
                                public static void Main(MainForm parent, TextBox output, FieldInfo[] privateFields) 
                                {
                                    try {";
                       //the code in a trycatch because i can send every error to a specific output defined as output parameter
                cmd += command;

                cmd += "}catch (Exception ex) { if(output != null){" +
                        "output.Text += ex.Message + \"\\n\\r\";"
                        +"}else{MessageBox.Show(ex.Message);}}}}}";
                try {
                    ExecuteCSharp(cmd);
                }
                catch (Exception ex) {
                    textBox2.Text += ex.Message + "\n\r";
                }
            }

        private void ExecuteCSharp(string code)
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            List<AssemblyName> assemblys = (Assembly.GetExecutingAssembly().GetReferencedAssemblies()).ToList<AssemblyName>();
            foreach (var item in assemblys) {
                parameters.ReferencedAssemblies.Add(item.Name + ".dll");
            }
            string t = Assembly.GetExecutingAssembly().GetName().Name;
            parameters.ReferencedAssemblies.Add(t + ".exe");
            //Here you have to reference every assembly the console wants access
            parameters.GenerateInMemory = true;
            parameters.GenerateExecutable = false;
            CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
            if (results.Errors.HasErrors) {
                StringBuilder sb = new StringBuilder();
                foreach (CompilerError error in results.Errors) {
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
                    }
                throw new InvalidOperationException(sb.ToString());
            }
            else {
                Assembly assembly = results.CompiledAssembly;
                Type program = assembly.GetType("ReflectionConsole.RuntimeExecution");
                MethodInfo main = program.GetMethod("Main");
                FieldInfo[] fields = this.GetType().GetFields(
                         BindingFlags.NonPublic |
                         BindingFlags.Instance);
                //if everything is correct start the method with some arguments:
                // containing class, output, private fields of the containing class for easier access
                main.Invoke(null, new object[]{this, textBox2, fields});
            }
        }
    }
}

一些说明:

您已经通过了包含其他所有内容的程序的最高类,因为与父对象相比,访问成员更容易。

您可以访问的公共对象,如parent.obect1.Text = "textXYZ";

您可以通过名称访问私有对象。 这些对象在privateFields中列出。 对于子类,您有两个选择:调用main.Invoke([...])时更改第一个和第三个参数, main.Invoke([...])私有字段。

作为建议,您可以在命令中包含.dll,这已经为您提供了实现此目标的方法。 例如GetValueFromFieldByName(object class, string name, Type resultType)

我希望这就是你所希望的^^

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM