SharpDevelop插件系统代码阅读笔记

2024-04-23 19:12

本文主要是介绍SharpDevelop插件系统代码阅读笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SharpDevelop插件系统代码阅读笔记

1.插件系统实现细节


/// <summary>
///AddIn.cs 通过在插件dll里面查找类名,再创建对象,这个功能MEF已经可以实现了
/// </summary>
/// <param name="className"></param>
/// <returns></returns>
public object CreateObject(string className)
{Type t = FindType(className);if (t != null)return Activator.CreateInstance(t);elsereturn null;
}

该方法的缺点就是需要传入类名,那么就需要在xml文件里面显示的将类名标记出来,再去解析。但是MEF功能通过Attribute就可以实现,不需要在xml里面显示的标记出来。但是,AddIn的组织方式肯定还是有其独到之处,继续往下看。
那么,获取到对象之后,是怎么组织管理起来的呢,是怎么插入到树节点中去的呢?

2.菜单栏的实现

static object CreateMenuItemFromDescriptor(MenuItemDescriptor descriptor)
{Codon codon = descriptor.Codon;string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Command";bool createCommand = codon.Properties["loadclasslazy"] == "false";switch (type) {case "Separator":return new MenuSeparator(codon, descriptor.Parameter, descriptor.Conditions);case "CheckBox":return new MenuCheckBox(codon, descriptor.Parameter, descriptor.Conditions);case "Item":case "Command":return new MenuCommand(codon, descriptor.Parameter, descriptor.Conditions);case "Menu":return new Menu(codon, descriptor.Parameter, ConvertSubItems(descriptor.SubItems), descriptor.Conditions);case "Builder":return codon.AddIn.CreateObject(codon.Properties["class"]);default:throw new System.NotSupportedException("unsupported menu item type : " + type);}
}

上面这段代码在MenuService.cs里面定义,菜单栏是AddIn应用的地方之一。
思考:如何结合MEF和AddIn框架在一起?
我的现有代码里面的菜单栏是通过大量重写基类实现的,这样做对后续的扩展并不友好。因此,还是想能不能将插件系统引入到我的项目中来。虽然在反射部分有些许区别,但是这点区别可以先忽略不计。
主要功能:
1.xml文件的结构和解析
2.

菜单栏命令所在文件
SharpDevelop\src\Main\Base\Project\Src\Commands\FileCommands.cs

public class OpenFile : AbstractMenuCommand
{public override void Run(){using (OpenFileDialog fdiag  = new OpenFileDialog()) {fdiag.AddExtension    = true;fdiag.Filter = ProjectService.GetAllFilesFilter();fdiag.FilterIndex     = 0;fdiag.Multiselect     = true;fdiag.CheckFileExists = true;if (fdiag.ShowDialog(SD.WinForms.MainWin32Window) == DialogResult.OK) {OpenFiles(Array.ConvertAll(fdiag.FileNames, FileName.Create));}}}protected virtual void OpenFiles(FileName[] fileNames){foreach (var name in fileNames) {SD.FileService.OpenFile(name);}}
}

如上面代码,继承自 AbstractMenuCommand

2. 项目树

public abstract class AbstractProjectBrowserTreeNode : ExtTreeNode, IDisposable

ProjectBrowserPanel 这个里面应该有项目Pad里面的右键菜单

public ProjectBrowserPanel(){projectBrowserControl      = new ProjectBrowserControl();projectBrowserControl.Dock = DockStyle.Fill;Controls.Add(projectBrowserControl);if (SD.AddInTree.GetTreeNode("/SharpDevelop/Pads/ProjectBrowser/ToolBar/Standard", false) != null) {toolStrip = SD.WinForms.ToolbarService.CreateToolStrip(this, "/SharpDevelop/Pads/ProjectBrowser/ToolBar/Standard");toolStrip.ShowItemToolTips  = true;toolStrip.Dock = DockStyle.Top;toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;toolStrip.Stretch   = true;standardItems = new ToolStripItem[toolStrip.Items.Count];toolStrip.Items.CopyTo(standardItems, 0);Controls.Add(toolStrip);}projectBrowserControl.TreeView.BeforeSelect += TreeViewBeforeSelect;}

SD.AddInTree.GetTreeNode()和SD.WinForms.ToolbarService.CreateToolStrip()这两个方法是关键。

WinFormsToolbarService
ToolbarService.CreateToolStrip(object owner, string addInTreePath)
AddInTree.GetTreeNode(addInTreePath)

public static AddInTreeNode GetTreeNode(string path, bool throwOnNotFound = true)
{var addInTree = ServiceSingleton.GetRequiredService<IAddInTree>();return addInTree.GetTreeNode(path, throwOnNotFound);
}public AddInTreeNode GetTreeNode(string path, bool throwOnNotFound = true)
{if (path == null || path.Length == 0) {return rootNode;}string[] splittedPath = path.Split('/');AddInTreeNode curPath = rootNode;for (int i = 0; i < splittedPath.Length; i++) {if (!curPath.ChildNodes.TryGetValue(splittedPath[i], out curPath)) {if (throwOnNotFound)throw new TreePathNotFoundException(path);elsereturn null;}}return curPath;
}//TreeNode是怎么创建的
AddInTreeNode CreatePath(AddInTreeNode localRoot, string path)
{if (path == null || path.Length == 0) {return localRoot;}string[] splittedPath = path.Split('/');AddInTreeNode curPath = localRoot;int i = 0;while (i < splittedPath.Length) {if (!curPath.ChildNodes.ContainsKey(splittedPath[i])) {curPath.ChildNodes[splittedPath[i]] = new AddInTreeNode();//ChildNodes是一个哈希表,key是节点名字,value只是一个实例}curPath = curPath.ChildNodes[splittedPath[i]];++i;}return curPath;
}

3.1 项目窗口

public static void ShowProjectOptions(IProject project)
{if (project == null){return;}foreach (IViewContent viewContent in SD.Workbench.ViewContentCollection){ProjectOptionsView projectOptions = viewContent as ProjectOptionsView;if (projectOptions != null && projectOptions.Project == project){projectOptions.WorkbenchWindow.SelectWindow();return;}}try{AddInTreeNode projectOptionsNode = AddInTree.GetTreeNode("/SharpDevelop/BackendBindings/ProjectOptions/" + project.Language);ProjectOptionsView projectOptions = new ProjectOptionsView(projectOptionsNode, project);SD.Workbench.ShowView(projectOptions);}catch (TreePathNotFoundException){MessageService.ShowError("${res:Dialog.ProjectOptions.NoPanelsInstalledForProject}");}
}

项目树的解析

public ProjectBrowserPanel()
{projectBrowserControl      = new ProjectBrowserControl();projectBrowserControl.Dock = DockStyle.Fill;Controls.Add(projectBrowserControl);if (SD.AddInTree.GetTreeNode("/SharpDevelop/Pads/ProjectBrowser/ToolBar/Standard", false) != null) {toolStrip = SD.WinForms.ToolbarService.CreateToolStrip(this, "/SharpDevelop/Pads/ProjectBrowser/ToolBar/Standard");toolStrip.ShowItemToolTips  = true;toolStrip.Dock = DockStyle.Top;toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;toolStrip.Stretch   = true;standardItems = new ToolStripItem[toolStrip.Items.Count];toolStrip.Items.CopyTo(standardItems, 0);Controls.Add(toolStrip);}projectBrowserControl.TreeView.BeforeSelect += TreeViewBeforeSelect;
}
```cpp
/// <summary>
/// 查看解决方案
/// </summary>
/// <param name="solution"></param>
public void ViewSolution(ISolution solution)
{AbstractProjectBrowserTreeNode solutionNode = new SolutionNode(solution);treeView.Clear();solutionNode.AddTo(treeView);foreach (var treeObject in solution.Items)//Items里面是数据{if (treeObject is IProject){NodeBuilders.AddProjectNode(solutionNode, (IProject)treeObject);//如果是Project,则加入到Builders里面}else{SolutionFolderNode folderNode = new SolutionFolderNode((ISolutionFolder)treeObject);//文件夹节点folderNode.InsertSorted(solutionNode);//讲自己插进父亲节点中}}solutionNode.Expand();//展开
}

4 系统里面那么多右键菜单怎么实现

public class ProjectBrowserPanel : System.Windows.Forms.UserControl
{
ToolStrip toolStrip;//工具栏
ProjectBrowserControl projectBrowserControl;//项目浏览器控件

/// <summary>
/// 从一个解决方案(Solution)中构建一个树视图
/// </summary>
/// <param name="solution"></param>
public void ViewSolution(ISolution solution)
{AbstractProjectBrowserTreeNode solutionNode = new SolutionNode(solution);treeView.Clear();solutionNode.AddTo(treeView);//创建一个解决方案节点(solutionNode),并将其添加到树视图中。foreach (var treeObject in solution.Items)//Items里面是数据,遍历解决方案中的每个项目和服务器{if (treeObject is IProject){NodeBuilders.AddProjectNode(solutionNode, (IProject)treeObject);//对于每个项目,创建一个项目节点(projectNode)并将其添加到项目节点中。}else{SolutionFolderNode folderNode = new SolutionFolderNode((ISolutionFolder)treeObject);//对于每个文件夹,创建一个文件夹节点(folderNode)。folderNode.InsertSorted(solutionNode);//并将folderNode插入到父节点中}}solutionNode.Expand();//展开解决方案节点以显示树视图。
}

这篇关于SharpDevelop插件系统代码阅读笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929636

相关文章

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文