返回首页

{A}
{S0}简介
代码片段是Visual Studio中,可以大大提高生产力的优秀功能。不过,我觉得在C#中,它们是在两个方面略有缺乏:他们不打开括号自动完成关闭括号。对于最普遍使用的片段,键入所需的语句出现是自然(按Tab键)。
例如,对于一个如果语句的代码片断火,你必须键入quot; iquot; quot; fquot;,然后quot; tabquot,然后quot; tabquot;这肯定是最好的类型quot; iquot,然后quot; fquot,然后quot; spacequot,代码片段出现。这是更自然,少了一个按键。我不知道在C的百分比#编码​​谁也不知道代码片段的存在,因为这个!
幸运的是,微软已经作出这种行为很容易地覆盖使用的可扩展性检查文本的用户刚刚进入,然后操纵它。
在做三件事:代码语句,如if,开关,,foreach和输入一个空格或换行符后运行相应的代码片段检查输入的文字。检查如(打开支架,然后自动添加相应的闭括号。{左大括号后,一个相应的结束括号}将增加。
这些选项可以由用户配置。背景
Visual Studio扩展的一个大背景下,本网站上的优秀LineCounter项目。安装
演示文件解压缩到一个文件夹的某处。移动quot; Jonno彗星#AutoComplete.AddInquot;文件到您的quot;你的路径\我的文档\ Visual Studio 2008的\ Addinsquot;文件夹。打开文件,并更改以下行指向的文件的位置:
如果您正在运行的源,然后quot; Jonno C#中AutoComplete.AddInquot;文件可能会丢失。将它加入到添加项目,确保您链接到您的加载项文件夹的版本,而不是将其添加。
如果你想运行单元测试,你将需要3.6 NUnit的2.5和Rhino Mocks的。
我只测试在Visual Studio 2008。选项
期权的形式,可以从菜单项加载在工具- GT; Jonno C#的自动完成选项。
选项保存为XML文件在同一文件夹作为附加在大会。
有三个选项卡上的形式:片段,支架,和括号。让我们来看看每个人。片段

这是一个简单的片段,将检查网格视图。如果你不喜欢一个条目,然后简单地将其删除。如果你觉得缺少的东西,然后把它添加或编辑现有条目。
网格视图中的文本将要检查的文本,字符串的最后一个字符的按键,将火灾的代码片段。
,例如第一项quot;如果quot;意味着,当用户按下空格(最后一个字符),它会检查,看看如果在前文quot; ifquot;如果是,那么按键将被取消,发送到窗口的选项卡火的代码片段。
进入quot; / rquot;将做同样的事情,除了它激发一个换行符,而不是一个空间的代码片段。
所以,如果你想在一个代码段声明火灾后输入quot; quot;,添加字符串quot;做quot;列表。如果你还希望它发射一个换行符,添加字符串quot;做\ rquot;,或者如果你不希望它火,从列表中删除。
显然,这个工作,您的代码段必须有一个相匹配的列表中的文本的捷径,即加入"XXX quot;列表不会做,如果你没有一个代码片段与xxx的捷径!括号
{S2}
再次,这是一个网格视图。第一列是开幕式支架,以搜寻,第二列是右括号,将被自动添加。
因此,将(一)作为第一个字符)作为第二个手段,将被自动添加当用户按下(。
第一个和第二个字符是相同的报价,例如,'和',或quot;"。
如果字符是不同的,然后一个右括号只会被添加,如果有比开放在该行的括号的右括号。如果字符是相同的,那么收盘报价只会被添加引号是在该行奇。
再次,你可以添加,编辑,或删除,以满足您的口味。裤带

第一项匹配的工作原理如下(其中管|代表光标):{C}
按{将返回:

public string Myproperty { | }

而给予:
public void myMethod()

    |

按{将返回:
public void myMethod()

{

    |

}

一个真正的支撑不同,那里已经上线的文本产生以下在此,开放括号:
public void myMethod() |

按{将返回:
public void myMethod() {

    |

}

一个真正的支撑换行"选项前面的选项,与右大括号只添加后,用户按下后,原来的括号中输入的差异。
没有关闭选项。使用代码
大部分的逻辑处理中的VSKeyPressHelper类,所以我们需要为这个属性:
private VSKeyPressHelper KeyPressHelper { get; set; }

这是在Connect类的OnConnection方法的应用对象初始化,像这样:
this.ApplicationObject = (DTE2)application;

this.AddInInstance = (AddIn)addInInst;



this.KeyPressHelper = new VSKeyPressHelper(this.ApplicationObject);

挂接到的按键事件,我们需要一个类型TextDocumentKeyPressEvents的财产。我们还需要挂接到窗口事件的WindowEvents财产,像这样:
private TextDocumentKeyPressEvents TextDocKeyEvents { get; set; }



private WindowEvents WindowEvents { get; set; }

然后,在Connect类的OnConnection方法,我们挂钩的Windows事件,我们需要的,这是WindowActivated WindowCreated事件。
Events2 events = (Events2)this.ApplicationObject.Events;



this.WindowEvents = (WindowEvents)events.get_WindowEvents(null);

this.WindowEvents.WindowActivated += 

   new _dispWindowEvents_WindowActivatedEventHandler(this.WindowActivated);

this.WindowEvents.WindowCreated += 

   new _dispWindowEvents_WindowCreatedEventHandler(this.WindowCreated);

当然,我们需要在Connect类的OnDisconnection方法来解开这一事件:
if (this.WindowEvents != null)

{

    this.WindowEvents.WindowActivated -= 

      new _dispWindowEvents_WindowActivatedEventHandler(this.WindowActivated);

    this.WindowEvents.WindowCreated -= 

      new _dispWindowEvents_WindowCreatedEventHandler(this.WindowCreated);

}

WindowActivated WindowCreated事件的处理程序,然后检查是否我们在C#文件,或通过检查窗口的最后三个字符已激活:
private void WindowCreated(Window created)

{

    this.AddKeyboardEventsIfFileIsaCSharpFile(created.Caption);            

}



private void WindowActivated(Window gotFocus, Window lostFocus)

{

    this.AddKeyboardEventsIfFileIsaCSharpFile(gotFocus.Caption);

}



private void AddKeyboardEventsIfFileIsaCSharpFile(string fileName)

{

    this.RemoveKeyboardEvents();



    if (fileName.EndsWith(".cs") || fileName.Contains(".cs "))

    {

        this.SetUpKeyboardEventsHandler();

    }

}

,如果它是一个C#文件,然后将键盘事件的处理。这意味着,添加在C#文件,而不是VB.NET是不必要的唯一作品。我们BeforeKeyPress和AfterKeypress事件感兴趣。他们首先获得脱钩RemoveKeyboardEvents方法,然后在SetUpKeyboardEventsHandler方法添加的。
Events2 events = (Events2)this.ApplicationObject.Events;

this.TextDocKeyEvents = (TextDocumentKeyPressEvents)

                           events.get_TextDocumentKeyPressEvents(null);



this.TextDocKeyEvents.BeforeKeyPress += 

  new _dispTextDocumentKeyPressEvents_BeforeKeyPressEventHandler(this.BeforeKeyPress);

this.TextDocKeyEvents.AfterKeyPress += 

  new _dispTextDocumentKeyPressEvents_AfterKeyPressEventHandler(this.AfterKeyPress);

让我们深入到的BeforeKeyPress方法:
// This handles the code snippets checking

if (this.KeyPressHelper.CheckForCodeSnippet(selection, keypress))

{

    cancelKeypress = true;

    

    // sends escape first to exit out of intellisense if it is open

    // if it is not open it does not matter.

    SendKeys.Send("{esc}");

    SendKeys.Send("{tab}");

}

使用的按键与当前选择的CheckForCodeSnippet决定,如果刚刚进入一个我们感兴趣的短语。如果是的话,那么我们发送逃生活动窗口。如果它是开放的的,这将取消的IntelliSense。我们再发送到活动窗口,火灾的代码片段(如果存在)的标签。
CheckForCodeSnippetStatement方法,从选点向后移动,输入,然后移动选择点在哪里,像这样:
private string GetPreviousTextFromSelectionPoint(EditPoint ep, EditPoint sp, int length)

{

    sp.CharLeft(length);

    var text = sp.GetText(ep);

    sp.CharRight(length);

    return text;

}

然后比较文本与quot; ifquot看看进入"; ifquot;声明。
AfterKeyPress方法操纵文本周围选择一个类似的方式。
的主要区别是如何处理文本。活动窗口发送键,我们可以直接插入文字,使用的选择和编辑点,如代码,插入一个结束括号:
sp.Insert(reverse);

selection.CharLeft(false, 1);

第一行插入支架,然后选择移动到左侧。 VSKeyPressHelper类的代码的其余部分类似的原则。
一个代码与连接类创建工具窗口和菜单很多,我就不详细。注意其他类XMLHelper类保存和加载设置和从XML文件,并OptionsView这是用来设置选项的工具窗口。兴趣点
这种类型的项目的第一个烦恼是,自动化单元测试是非常困难的!因此,移动选点和插入文本涉及的试验和错误的位之前得到它的权利。我已经添加在可能的情况下,我觉得这是不值得的努力,以测试连接类或VSKeyPressHelper类的单元测试。
大多数骨为首的事情,我也没有占到评论!我加入后使用了一段时间,这对于一个quot检查LineContainsCSharpComments方法; / / quot;之前输入的文本,并关闭的行为,如果它的存在。历史9月7日,2009年的最初版本。九月十四日,2009年:新增片段,括号,括号风格的配置。添加到源代码,单元测试实际。重构代码基地。9月15日,2009年:加入WindowCreated事件的处理。

回答

评论会员:itsho 时间:2012/01/25
伟大的文章,但代码片段使整个事情无关
评论会员:manu018 时间:2012/01/25
建议感谢
fsfsdfsdfsdfsdfsdf
sdfsdfsdfs
DF

SD
F
SD
消防处
FS
dfsd
消防处
fsdf

自卫队
SD
评论会员:korcutt 时间:2012/01/25
您好,
我很好奇,如果像这样一直把Visual Studio 2005和VB.Net??或有没有人看着移植这个/下的早期版本?...{ BR}
在此先感谢,

凯文Orcutt
评论会员:elizas 时间:2012/01/25
Visual Studio 2008中让生活很容易为开发。我们可以自动创建完整的代码块。这是在一个非常VB.NET先进水平,目前仍在演变为C#。右击并从上下文菜单中选择"插入片段"或者使用Ctrl KX,你会看到一个菜单,它列出了所有可用的选项都整齐分组。

只为一个样,我用插入片段创建一个代码块"呼叫一个SqlCommand的ExecuteReader方法" -
感谢
伊丽莎


欢呼声,
伊丽莎
评论会员:thatraja 时间:2012/01/25

呀5
评论会员:拉杰什皮莱 时间:2012/01/25
非常有用。

享受生活,
拉杰什皮莱
http://rajeshpillai.blogspot.com/
http://simply-url.blogspot.com/

评论会员:NightElfik 时间:2012/01/25
我在Eclipse工作,有这样的行为非常好一段时间。我使用压缩的语法少像:
if(true){

  for(;;){

    

  }

}
此语法是没有工作...

最优行为是当按下后进入"{"将添加"}",并设置光标在中间,所以
if(true){<enter>
会产生
if(true){

  <cursor>

}

继续工作...

| FatGeek
评论会员:游客 时间:2012/01/25
我在未来的版本将添加这是一个选项
pmj2
评论会员:游客 时间:2012/01/25
早在80年代末(!是的,20年前)的迷雾,简短的文字编辑器会愉快地完成,如果statments,括号,{}为你,甚至产生整个街区,例如;spacegt进入傻瓜,会导致以下:codeprespanclass="code-keyword"do/span{b|/b}spanclass="code-keyword"while/span();/pre/code它的位置光标('|'上面),这是有意义的继续打字最后,您的添加带来的是这片古老而有用的功能,VS(当然,它的一个位,反正!)万岁简短
!FatGeek
评论会员:游客 时间:2012/01/25
!我正要说我的时间之前的这短暂的,但后来我googled,它仍然是可用我会做"标准报表的清单,在未来的版本{BR检查}:仙女座瞬
哦我现在不逗!如果你这样做,你将有一个生活中的朋友{五}
评论会员:pmj2 时间:2012/01/25
!喜

大加载项,您非常多。

我会感兴趣的用户界面,例如添加配置禁用完成'('和'[' - 我使用DevExpress,它提供了一个改进完成的功能,但不完整的'{'.{ BR}
评论会员:。橡树Chantosa 时间:2012/01/25
好主意,我会更新添加选项对话框可能能够做到这一点之前的周末
评论会员:。pmj2 时间:2012/01/25
in connect.cs

 

.

.

.

 

case "[":

case "(":

case "\"":  // add this

case "'":   // and this

.

.

.

 

in VSKeyPressHelper.cs

 

        private string GetReverseBracket(string openBracket)

        {

            switch (openBracket)

            {

                case "(":

                    return ")";

 

                case "[":

                    return "]";

 

                case "\"":  // case of double quote

                    return "\"";

 

                case "'":  // case of single quote

                    return "'";

            }

 

            return string.Empty;

        }

 

        public void AddEndBracketAfterOpenBracket(TextSelection selection, EditPoint sp, string keyPress)

        {

            var reverse = this.GetReverseBracket(keyPress);

 

            // if keyPress *is* equal to reverse, then it's probably quotes

            if ((keyPress != reverse) && !this.CheckForLessCloseBracketsThanOpenBrackets(sp, keyPress, reverse))

            {

                return;

            }

 

            sp.Insert(reverse);

            selection.CharLeft(false, 1);

        }