[Visual Studio]Code Snippet

在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for、foreach ? 在编写这两个循环语句的时候,你是一个字符一个字符敲还是使用 Visual Studio 提供的Code Snippet 工具自动帮你生成呢?

神奇之处
  你只需要在代码编辑器中输入for,就会看到 Visual Studio 的自动提示框中出现了如下红框框起来的部分,这个时候只需要连按两下 tab 键,便会自动补全 for 循环语句(如图2所示),并且默认选中索引,以便你进行修改。
在这里插入图片描述图 1 自动提示框
在这里插入图片描述
图 2 自动补全循环语句

是不是很神奇? 与之类似的还有switch、cw (Console.WriteLine)、ctor(构造器)、prop(属性)等,灵活运用这些就可以让你的 Coding 工作事半功倍,更多默认 CodeSnippet 请查看参考资源[1]。
  但是,每个项目都有每个项目的特殊性,默认的这些 Code Snippet 如果无法满足您的需求,这个时候就需要自动动手来扩展了。

Code Snippet 的神秘面纱【C#】

在动手开始写自己的 Code Snippet 之前,得先搞清楚这个玩意儿是怎么做到的。
  它其实只是一个 xml,只不过包含了一些只有 Visual Studio 才认识的元素,这些元素就定义了如何去替我们补全代码(,Code Snippet 针对不同的语言如VB、C#、CSS使用不同的元素,本文全部按照 C# 语言进行介绍)。

下面来看一下 for 的Snippet源代码是长什么样子的

 <?xml version="1.0" encoding="utf-8"?>
 <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
     <CodeSnippet Format="1.0.0">
         <Header>
             <Title>for</Title>
             <Shortcut>for</Shortcut>
             <Description>for 循环的代码段</Description>         
             <Author>Microsoft Corporation</Author>        
             <SnippetTypes>           
                 <SnippetType>Expansion</SnippetType>               
                 <SnippetType>SurroundsWith</SnippetType>           
             </SnippetTypes>      
         </Header>    
         <Snippet>    
             <Declarations>           
                 <Literal>            
                     <ID>index</ID>                 
                     <Default>i</Default>                   
                     <ToolTip>索引</ToolTip>              
                 </Literal>               
                 <Literal>            
                     <ID>max</ID>               
                     <Default>length</Default>                  
                     <ToolTip>最大长度</ToolTip>            
                 </Literal>           
             </Declarations>          
             <Code Language="csharp"><![CDATA[for (int $index$ = 0; $index$ < $max$; $index$++)        
             {      
                 $selected$ $end$          
             }]]>        
             </Code>      
         </Snippet>   
     </CodeSnippet>
 </CodeSnippets>

一个 CodeSnippet 则主要包含

和 两部分。上面的结构挺清晰的,一个 元素可以包含多个不同的 。
  其中
部分主要是对这个 Snippet 的一个声明,包括 Snippet 的名称、描述、作者及 Snippet 的类型(稍后会解释)。
在这里插入图片描述
Header 部分在实际运行中的作用

元素

snippet元素是关键的重点,单独弄一节来具体说明。
  完整的 snippet 元素结构如下:

 <Snippet>
     <Declarations>... </Declarations>
     <Code>... </Code>
 </Snippet>

元素

该元素用于定义在运行中需要被替换的变量,Microsoft 提供了两种类型:Literal(文本)和 Object(对象)。MSDN上的解释如下:

Literal
元素用于标识整体包含在代码段中、但在插入到代码中后可能会进行自定义的代码部分的替换对象。例如,字符串、数字值以及应声明为文本的一些变量名。

Object 元素用于标识代码段所需的、但可能是在代码段外部定义的项。例如,Windows 窗体控件、ASP.NET
控件、对象实例以及类型实例应声明为对象。对象声明需要指定类型。

至于这两者在实际运用中的区别,我还真不清楚。如果哪位大侠对此了解,还望指点一二。下面只介绍 Literal 类型。

完整的 结构如下:

 <Literal Editable="true/false">
    <ID>... </ID>
    <ToolTip>... </ToolTip>
    <Default>... </Default>
    <Function>... </Function>
 </Literal>

ID 用于指定需要被替换的对象名称,有且只有一个。Editable 意味在生成代码过程中能不能直接替换成我们想要文本,比如 for 循环中的索引变量,默认是 “i”,但是我们可以替换成任何自己想要的,比如 “Index”。

Default 表示默认生成代码时,该对象将被 Default 值给代替。

Function 指示当该对象在获取焦点的时候将要执行的方法。在 Visual Studio 中目前只支持三个方法:GenerateSwitchCases(EnumerationLiteral)、ClassName()、SimpleTypeName(TypeName)。

其中 GenerateSwitchCases 顾名思义是用于为switch的变量生成case条件的。
在这里插入图片描述在这里插入图片描述
  ClassName方法用于获取当前的类名。

SimpleTypeName 则用于缩短类型的名字,因为有些时候有些程序集不会被using进来,这个时候对该程序集中某一类型的调用就需要使用 “名称空间.类型名称” 这种方式。但是如果当前的文件已经把需要的程序集using进来了,那这种调用方式就显得是多此一举。通过使用 SimpleTypeName 就能在生成代码的时候帮助我们判断是否需要加上名称空间这个前缀。

元素

这才是我们的主角,因为我们的代码就是写在了该元素内部。先来看一个例子:

 <Code Language="csharp"><![CDATA[for (int $index$ = 0; $index$ < $max$; $index$++)     
 {      
     $selected$ $end$          
}]]>
 

上面的代码相当简单,所有需要在生成代码的时候被替换的内容都用 $ 包裹,如 i n d e x index index,记住这个被包裹的内容必须在 被正确定义过。因为代码中可能会有一些在XML中有特殊含义的字符,所以用CDATA进行包裹,防止错误转义。
   s e l e c t e d selected selected e n d end end 是保留的关键字,其中 e n d end end 用于指示当代码插入完毕后,光标应该位于的位置。 s e l e c t e d selected selected 用于表示在生成代码前你所选中的文本,并在生成代码的过程中使用你选中的文本替换 s e l e c t e d selected selected,常用于 SurroundWith 这种类型的 Code Snippet 中。

Snippet 类型

根据我们的使用方式,snippet 分为 Expansion、SurroundsWith 及 Refactoring(只能在重构过程中使用,自定义的 Code Snippet 不能使用)。

Expansion:允许将代码段插入到光标处。

SurroundsWith:允许将此代码段放置在一段选定的代码周围。比如我们写完一段代码后,发现忘记加 try…catch… 了,这个时候可以选中需要包裹在 try…catch… 中的代码,然后调用 Code Snippet。

如何自定义一个 snippet

如果对上面的结构有了基本了解,下面就来实践一下吧。通过本节,我们要实现自动生成 Debug.WriteLine 的 snippet。
  首先,打开 Visual Stuido / 文件 / 新建 / 文件,选择 xml 类型。
  在 xml 文件中,输入最小的snippet代码。

 <?xml version="1.0" encoding="utf-8"?>
 <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
     <CodeSnippet Format="1.0.0">
         <Header>
             <Title></Title>
         </Header>
         <Snippet>
             <Code Language="">
                 <![CDATA[]]>
             </Code>
         </Snippet>
     </CodeSnippet>
 </CodeSnippets>

修改如上的代码,包括 Header 部分和 Snippet 部分,别忘记指定Language。

 <?xml version="1.0" encoding="utf-8"?>
 <CodeSnippets    xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
   <CodeSnippet Format="1.0.0">
     <Header>
       <Title>dw</Title>
       <Description>Debug.WriteLine</Description>
       <Shortcut>dw</Shortcut>
       <Author>Charley</Author>
     </Header>
     <Snippet>
       <Declarations>
         <Literal>
           <ID>text</ID>
           <ToolTip>希望输出的内容</ToolTip>
           <Default>"text"</Default>
         </Literal>
       </Declarations>
       <Code Language="csharp">
         <![CDATA[Debug.WriteLine($text$);$end$]]>
       </Code>
     </Snippet>
   </CodeSnippet>
 </CodeSnippets>

如果嫌自己写太麻烦,也可以使用开源的 snippet 编辑工具,详见参考资源[2]。
Snippet 的管理
  新建完一个snippet之后,该如何才能在项目中用起来呢?
  工具 / 代码段管理器 打开管理器。在这里插入图片描述
使用 “导入” 将自定义的文件导入进来。在这里插入图片描述
 为自己的 snippet 选择一个位置。在这里插入图片描述
  点击完成就已经成功了。在代码编辑器中,输入 dw 就会发现 Visual Stuido 的智能提示已经出现了我们的 snippet。
在这里插入图片描述

如何使用 SurroundWith 类型的 Snippet?

相比于 Expansion 类型的 snippet,使用 SurroundsWith 相对要麻烦点。
本人认为最快捷的方式就是使用键盘快捷键,在代码编辑器中 CTRL+K, CTRL+S,就可以呼出 snippet。在这里插入图片描述
  然后用键盘或鼠标选择目标 snippet。

参考资源

[1] Visual C# Code Snippets
[2] Snippet Editor
本文来源于 《使用 Code Snippet 简化 Coding》

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…