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);
    else
        return 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);
            else
                return 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.mfbz.cn/a/570231.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣刷题 70.爬楼梯

题干 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2. 2 阶 示例 2&…

机器学习和深度学习 -- 李宏毅(笔记与个人理解)Day 23

Day 23 Self - Atention 变形 关于很多个former 的故事 痛点&#xff1a; 在于做出注意力矩阵之后的运算惊人 由于self - attention 一般都是在big model 的一部分&#xff0c;所以&#xff0c;一般不会对模型造成决定性的影响&#xff0c; 只有当model 的输入较长的时候&am…

求臻医学MRD产品斩获2023年度肿瘤标志物年度十大创新技术产品奖

2024年4月20日&#xff0c;中国肿瘤标志物学术大会开幕式暨名家讲坛在南京隆重召开! 会议期间&#xff0c;中国抗癌协会肿瘤标志专业委员会联合中国抗癌协会肿瘤临床检验与伴随诊断专业委员会、中国抗癌协会肿瘤基因诊断专业委员等共同发布“2023 年度肿瘤标志物创新技术产品”…

Java 提取HTML文件中的文本内容

从 HTML 文件中提取文本内容是数据抓取中的一个常见任务&#xff0c;你可以将提取的文本信息用于编制报告、进行数据分析或其他处理。本文分享如何使用免费 Java API 从HTML 文件中提取文本内容。 安装免费Java库&#xff1a; 要通过Java提取HTML文本&#xff0c;需要用到Free…

C语言实现双人贪吃蛇项目(基于控制台界面)

一.贪吃蛇 贪吃蛇是一款简单而富有乐趣的游戏&#xff0c;它的规则易于理解&#xff0c;但挑战性也很高。它已经成为经典的游戏之一&#xff0c;并且在不同的平台上一直受到人们的喜爱和回忆。 二.贪吃蛇的功能 游戏控制&#xff1a;玩家可以使用键盘输入设备来控制蛇的移动方…

基于模糊控制的纯跟踪横向控制在倒车中的应用及实现

文章目录 1. 引言2. Pure Pursuit在倒车场景的推导3. 模糊控制器的设计3.1 基础知识3.2 预瞄距离系数k的模糊控制器设计 4. 算法和仿真实现 1. 引言 Pure Pursuit是一种几何跟踪控制算法&#xff0c;也被称为纯跟踪控制算法。他的思想就是基于当前车辆的后轮中心的位置&#x…

Axure RP 9 for Mac/win:打造极致交互体验的原型设计神器

在数字化浪潮席卷全球的今天&#xff0c;原型设计作为产品开发的关键环节&#xff0c;其重要性不言而喻。Axure RP 9&#xff0c;作为一款专为设计师和开发者打造的原型设计软件&#xff0c;以其出色的交互设计能力和高效的协作体验&#xff0c;赢得了广大用户的青睐。 Axure …

【JavaScript】axios

基础使用 <script src"https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script> <script>axios.get(https://study.duyiedu.com/api/herolist).then(res> {console.log(res.data)}) </script>get - params <script s…

U盘乱码频发,原因与解决方案大揭秘

在日常的工作和生活中&#xff0c;U盘因其便携性和大容量成为了我们不可或缺的存储设备。然而&#xff0c;有时候我们会遭遇U盘乱码的问题&#xff0c;这让我们无法正确读取和使用其中的文件。那么&#xff0c;U盘乱码究竟是何原因导致的呢&#xff1f;又该如何解决这一问题呢&…

Python自学之路--002:Python 如何生成exe可执行文件

目录 1、概述 2、安装pyinstall 3、终端指令 1、概述 大部分时候&#xff0c;执行的仅仅是一个Python解释器出来的文件&#xff0c;至于怎么将文件生成exe的可执行文件呢&#xff1f;Python有对应的库&#xff0c;也就是pyinstall。安装之后产生dist文件夹&#xff0c;里面就…

UE5 GAS开发P34 游戏效果理论

GameplayEffects Attributes&#xff08;属性&#xff09;和Gameplay Tags&#xff08;游戏标签&#xff09;分别代表游戏中实体的特性和标识。 Attributes&#xff08;属性&#xff09;&#xff1a;Attributes是用来表示游戏中实体的特性或属性的值&#xff0c;例如生命值、…

ffmpeg的安装以及使用

1.FFmpeg 的主要功能和特性&#xff1a; 格式转换&#xff1a;FFmpeg 可以将一个媒体文件从一种格式转换为另一种格式&#xff0c;支持几乎所有常见的音频和视频格式&#xff0c;包括 MP4、AVI、MKV、MOV、FLV、MP3、AAC 等。视频处理&#xff1a;FFmpeg 可以进行视频编码、解…

书生·浦语大模型开源体系(四)作业

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

云计算技术架构及发展

云计算是指一种将可伸缩、弹性、共享的物理和虚拟资源池以按需自服务的方式供应和管理&#xff0c;并提供网络访问的模式。 云计算服务商利用分布式计算和虚拟资源管理等技术&#xff0c;通过网络将分散的ICT资源集中起来形成共享的资源池&#xff0c;并以动态按需和可度量的方…

基于若依和flowable7.0.1的ruoyi-nbcio-plus流程管理系统正式发布

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

皮带机巡检解决方案

在化工行业中、皮带机人工巡检存在的疲劳安全、巡检质量、数据分析等问题&#xff0c;通过以智能巡检机器人为中心的设备生命周期运维管理系统&#xff0c;完成对皮带机的巡检巡逻和排查预警&#xff0c;有效降低人员和设备的安全隐患&#xff0c;更助力企业运维水平和智能化作…

人脸识别 ArcFace人脸识别

文章目录 损失函数的设计思路 损失函数的设计思路

电子温度计不准需要怎么处理?

电子温度计不准需要怎么处理&#xff1f; 首选将温度计完全浸入温度为0℃左右的水中&#xff0c;使温度计指示值与0℃相等&#xff0c;拿出测量待测物的温度。其次将温度计完全浸入温度为100℃左右的水中&#xff0c;使温度计指示值与100℃相等&#xff0c;拿出测量待测物的温…

【InternLM实战营---第六节课笔记】

一、本期课程内容概述 本节课的主讲老师是【樊奇】。教学内容主要包括以下三个部分&#xff1a; 1.大模型智能体的背景及介绍 2. Lagent&AgentLego框架介绍 3.Lagent&AgentLego框架实战 二、学习收获 智能体出现的背景 智能体的引入旨在克服大模型在应对复杂、动态任…

redis单线程模型

工作原理 在Redis中&#xff0c;当两个客户端同时发送相同的请求时&#xff0c;Redis采用单线程模型来处理所有的客户端请求&#xff0c;会依次处理这些请求&#xff0c;每个请求都会按照先后顺序被执行&#xff0c;不会同时处理多个请求。使得Redis能够避免多线程并发访问数据…
最新文章