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();//展开解决方案节点以显示树视图。
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/2267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FLStudio怎么冻结轨道以及如何批量复制音符

FLStudio是一款功能强大的音乐制作软件&#xff0c;广泛用于音乐制作和打谱当中。我们在制作音乐时&#xff0c;经常会遇到处理大量音频轨道的情况&#xff0c;过多的音频轨道可能会导致电脑性能受限&#xff0c;从而影响工作流程。为了应对这个问题&#xff0c;FLStudio提供了…

【JavaEE多线程】Java 文件操作

目录 Java中操作文件File概述属性构造方法方法 文件内容的读写——文件流 streamInputStreamFileInputStream概述利用 Scanner 进行字符读取OutputStream 概述 练习 Java中操作文件 Java 中通过 java.io.File类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。注…

Ruby中Rack中间件的作用是什么?如何应用?

在 Ruby 中&#xff0c;Rack 是一个 Web 服务器接口&#xff0c;它允许开发者使用统一的方式构建 Web 应用程序。Rack 中间件是 Rack 框架的一个核心概念&#xff0c;它可以在请求被传递给应用程序之前或之后对请求和响应进行处理。 Rack 中间件的作用包括但不限于&#xff1a…

IPv6改造:反向代理技术的原理和优缺点分析

在前面几篇文章中&#xff0c;我们介绍了目前行业中三种比较常见的IPv6改造技术&#xff0c;分别是隧道技术、双栈技术和翻译技术&#xff0c;这三种改造方式采用不同的技术方案实现了IPv4向IPv6网络的过渡&#xff0c;然而每种改造技术在改造周期和成本、业务连续性、协议兼容…

实景景区亲自儿童剧本杀小程序开发搭建

实景景区亲自儿童剧本杀小程序开发搭建需要涉及多个方面的内容&#xff0c;包括系统架构设计、功能模块设计、页面设计、开发工具选择等。 系统架构设计需要确定小程序的开发框架&#xff0c;可以使用小程序开发框架来构建前端页面和后端接口&#xff0c;同时需要考虑数据库设…

ctfshow web入门 SQl注入 web185--web190

web185 这道题还有另外一个脚本就是用concat的拼接达到有数字的目的 concat(truetrue) 2 concat(true) 1 concat(true, true) 11 然后上脚本&#xff08;Y4tacker这个师傅的&#xff09; # Author:Y4tacker import requestsurl "http://341e93e1-a1e7-446a-b7fc-75beb…

目标检测——行人交通信号灯数据集

一、重要性及意义 行人交通信号灯检测的重要性及意义主要体现在以下几个方面&#xff1a; 首先&#xff0c;行人交通信号灯检测对于提高道路安全性至关重要。通过准确识别交通信号灯的状态&#xff0c;行人可以更加清晰地了解何时可以安全地过马路&#xff0c;从而避免与车辆…

node.js版本降级/升级

第一步.先清空本地安装的node.js版本 按健winR弹出窗口&#xff0c;键盘输入cmd,然后敲回车&#xff08;或者鼠标直接点击电脑桌面最左下角的win窗口图标弹出&#xff0c;输入cmd再点击回车键&#xff09; 进入命令控制行窗口&#xff0c;输入where node&#xff0c;查看本地…

Android Studio历史版本下载地址

https://developer.android.com/studio/archive?hlzh-cn https://blog.csdn.net/crasowas/article/details/130304836

STM32F4使用FPU/DSP核心启用与测试

STEP1、下载DSP库 具体链接如下&#xff1a; https://www.st.com/en/embedded-software/stsw-stm32065.html?dl9w6sdOSAKySFxBhN764Stg%3D%3D%2CIS1vzyA84KLAefK%2B0DawUl0FScREpiT6AdC3qFjIMJnCIgXIwr82G2XUFo6w43Wp5L5CUyrX3vZAoaHRE3nsTmRsArV3hnQOEgX73SKt8ss1vGrLlfXT24j…

【electron 4】electron配置打包环境

首先要准备应用图标 window需要&#xff1a;ico mac需要&#xff1a;icns linux需要png 借助&#xff1a;electron-icon-builder 安装&#xff1a; npm i electron-icon-builder -D配置package.json scripts "build-icon": "electron-icon-builder --input.…

js获取某月往前推一年或半年的年月数组

前言 需求&#xff1a;需要显示某月份往前推一年或者半年的费用情况&#xff0c;显示到柱形图上&#xff0c;后台接口只返回有数据的年份&#xff0c;这就需要前端拿全部月份数组去比对并显示。 开始 上代码&#xff1a; // date:选择的月份,比如:2024-04,//n:半年或者1年,…

完美解决多种情况下的 java.lang.NullPointerException 的异常

文章目录 1. 复现错误2. 分析问题3. 解决问题1. 复现错误 在工作中,经常会遇见java.lang.NullPointerException的异常,这种异常千奇百怪,但明确一点的是:它是空指针异常,也称之为NPE异常,如下代码所示: @Setter @Getter @Accessors(chain = true) public class Student…

【UE5.1 C++】VS2022下载安装

目录 步骤 一、Visual Studio下载安装 二、Visual Studio Integration Tool插件安装 先看一下UE和VS的兼容性 &#xff08;虚幻5&#xff1a;为虚幻引擎C项目设置Visual Studio开发环境&#xff09; &#xff08;虚幻4&#xff1a;设置虚幻引擎的Visual Studio&#xff0…

XiaodiSec day022 Learn Note 小迪安全学习笔记

XiaodiSec day022 Learn Note 小迪安全学习笔记 记录得比较凌乱&#xff0c;不尽详细 day22 主要内容 原生 js 款该 前端验证&未授权 开始 js 中也存在变量和函数&#xff0c;在浏览器中可以直接从浏览器中解析出&#xff0c;相当于白盒 而在之前的类似于 java 或 P…

libxml2读写XML文件测试

libxml2是一个功能强大的XML解析库&#xff0c;可以用于读取和写入XML文件。以下是一些基本的例子来展示如何使用libxml2进行读写操作。 写文件 在这个例子中&#xff0c;我们首先创建一个新的XML文档&#xff0c;并设置一个根节点。然后&#xff0c;我们创建两个新的节点&…

大型网站系统架构演化实例_6.使用分布式文件系统和分布式数据库系统

1.使用分布式文件系统和分布式数据库系统 任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后&#xff0c;从一台服务器拆分成两台服务器&#xff0c;但是随着网站业务的发展依然不能满足需求&#xff0c;这时需要使用分布式数据库。文件系统也一…

3dmax安装错误代码2146885616,也出现以下可选组件未成功安装:-Substance

当3dmax高版本出现安装错误代码2146885616&#xff0c;或者可选组件未成功安装:-Substance时&#xff0c;如图 解决方法如下 打开autoremove&#xff0c;点击扩展功能&#xff0c;搜索2146885616点击搜索 点击出现的按钮&#xff0c;提示如图&#xff0c;请重启电脑再点击一…

html网页在展示时,监听网络是否断网,如果断网页面暂停点击响应

序言&#xff1a; 集合百家之所长&#xff0c;方著此篇文章&#xff0c;废话少说&#xff0c;直接上代码&#xff0c;找好你的测试网页&#xff0c;进行配置&#xff0c;然后复制粘贴代码&#xff0c;就可以了。 1.css文件内容 #newbody{display: none;width: 100%;height: 9…