饭饭TXT > 学习管理 > 《Visual Studio 2010 高级编程(英文出书版)》作者:Nick Randolph/等【完结】 > [Visual.Studio.2010.高级编程].Professional.Visual.Studio.2010.txt

第 152 页

作者:Nick Randolph/等 当前章节:15362 字 更新时间:2026-6-18 14:51

comment and we can answer the query, we will try and find a way to refactor the code so that the

answer is obvious or supply a comment explaining why the code is the way it is (on the rare

occasion that the check comment exposes an error, we fix it). Using this technique, our code

becomes more maintainable over time as it gets easier to read and understand. We have tools that

allow us to extract a list of these comments from the code base, but it would be really handy if we

could highlight them within the code editor itself. The Check Comment Margin Highlighter does

just that by adding a glyph in the margin on the left (where breakpoints normally appear) for any

line that contains a comment that contains the token check:.

The code comes in two parts: a tagger and a glyph factory. Here is the complete code listing for

the tagger:

c#

using System;

using System.Collections.Generic;

extending the editor .

1051

using System.ComponentModel.Composition;

using Microsoft.VisualStudio.Text;

using Microsoft.VisualStudio.Text.Classification;

using Microsoft.VisualStudio.Text.Editor;

using Microsoft.VisualStudio.Text.Tagging;

using Microsoft.VisualStudio.Utilities;

namespace CheckCommentHighlighter

{

class CheckCommentTag : IGlyphTag { }

class CheckCommentTagger : ITagger<CheckCommentTag>

{

private readonly IClassifier _classifier;

public CheckCommentTagger(IClassifier classifier)

{

_classifier = classifier;

}

public IEnumerable<ITagSpan<CheckCommentTag>> GetTags(

NormalizedSnapshotSpanCollection spans)

{

foreach (var span in spans)

{

foreach (var classification in

_classifier.GetClassificationSpans(span))

{

var isComment = classification.ClassificationType

.Classification

.ToLower()

.Contains("comment");

if (isComment)

{

var index = classification.Span.GetText()

.ToLower().IndexOf("check:");

if (index != -1)

{

var tag = new CheckCommentTag();

var snapshotSpan = new SnapshotSpan(

classification.Span.Start + index, 6);

yield return new TagSpan<CheckCommentTag>(

snapshotSpan,

tag);

}

}

}

}

}

public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

1052 .

chaPter 53 mAnAged exTenSibiliTy FrAmeWork (meF)

}

[Export(typeof(ITaggerProvider))]

[TagType(typeof(CheckCommentTag))]

[ContentType("code")]

class CheckCommentTaggerProvider : ITaggerProvider

{

[Import]

private IClassifierAggregatorService AggregatorService;

public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag

{

if( buffer == null )

throw new ArgumentNullException("buffer");

var classifier = AggregatorService.GetClassifier(buffer);

return new CheckCommentTagger(classifier) as ITagger<T>;

}

}

}

Code snippet CheckCommentHighlighter\CheckCommentTagger.cs

Vb

Imports System.ComponentModel.Composition

Imports Microsoft.VisualStudio.Text

Imports Microsoft.VisualStudio.Text.Tagging

Imports Microsoft.VisualStudio.Text.Editor

Imports Microsoft.VisualStudio.Text.Classification

Imports Microsoft.VisualStudio.Utilities

Friend Class CheckCommentTag

Inherits IGlyphTag

End Class

Friend Class CheckCommentTagger

Implements ITagger(Of CheckCommentTag)

Private m_classifier As IClassifier

Friend Sub New(ByVal classifier As IClassifier)

m_classifier = classifier

End Sub

Private Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection)

As IEnumerable(Of ITagSpan(Of CheckCommentTag))

extending the editor .

1053

Implements ITagger(Of CheckCommentTag).GetTags

Dim Tags As New List(Of ITagSpan(Of CheckCommentTag))

For Each span As SnapshotSpan In spans

For Each classification As ClassificationSpan In

m_classifier.GetClassificationSpans(span)

If classification.ClassificationType.Classification.ToLower()

.Contains("comment") Then

Dim index As Integer = classification.Span.GetText().ToLower()

.IndexOf("check:")

If index <> -1 Then

Dim snapshotSpan As New SnapshotSpan(classification.Span.Start

+ index, 6)

Dim tag As New CheckCommentTag

Tags.Add(New TagSpan(Of CheckCommentTag)(snapshotSpan, tag))

End If

End If

Next classification

Next span

Return Tags

End Function

Public Event TagsChanged As EventHandler(Of SnapshotSpanEventArgs)

Implements ITagger(Of CheckCommentTag).TagsChanged

End Class

<Export(GetType(ITaggerProvider)), ContentType("code"),

TagType(GetType(CheckCommentTag))>

Friend Class CheckCommentTaggerProvider

Implements ITaggerProvider

<Import()>

Friend AggregatorService As IClassifierAggregatorService

Public Function CreateTagger(Of T As ITag)(ByVal buffer As ITextBuffer)

As ITagger(Of T) Implements ITaggerProvider.CreateTagger

If buffer Is Nothing Then

Throw New ArgumentNullException("buffer")

End If

Dim Classifier = AggregatorService.GetClassifier(buffer)

Dim tagger As New CheckCommentTagger(Classifier)

Return TryCast(tagger, ITagger(Of T))

End Function

End Class

Code snippet CheckCommentHighlighter\CheckCommentTagger.vb

1054 .

chaPter 53 mAnAged exTenSibiliTy FrAmeWork (meF)

Three classes are defined here. The first is the CheckCommentTag class. It inherits from IGlyphTag

but has no implementation on its own. It is purely a marker that identifies when a particular span of

text should have this glyph applied. We could have supplied some properties on the tag class to pass

information to the glyph factory later that could be used to affect the type of UIElement displayed.

The second class is the CheckCommentTagger class. This class is responsible for identifying

spans of text that should have the CheckCommentTag applied. It does this by implementing the

ITagger<CheckCommentTag> interface. This interface consists of a method called GetTags and a

TagsChanged event. GetTags takes a collection of spans and returns a collection of ITagSpans. In

this implementation, it finds all of the comments with the help of a classifier and searches for the

string check:. If it finds this string, it creates a new TagSpan<CheckCommentTag> item, which it

applies to just the span of text that covers the check: string.

The final class is CheckCommentTaggerProvider, which contains the MEF export metadata that

Visual Studio is looking for in the extension. This class is exported using the ITaggerProvider

contract, which means that Visual Studio will add it to an internal list of tagger providers to be called

upon whenever taggers are required. Two other pieces of metadata are also attached to this class. The

TagTypeAttribute specifies the type of tags that will be produced by any taggers that this provider

creates. The ContentTypeAttribute supplies a filter on the kinds of content on which this tagger

provider should be used. In this case, the attribute specifies that this tagger provider should only

be called upon when the editor contains code, which is a common base content type provided by

the editor.

The tagger provider class also has an import requirement for an IClassifierAggregatorService.

This service is used in the construction of taggers, which occurs in the CreateTagger<T>

method. This method is passed an ITextbuffer for which it is to provide a tagger. It uses

the AggregatorService to retrieve a classifier and then uses the classifier to construct the

CheckCommentTagger defined in the previous code snippet.

This code is enough to allow Visual Studio to mark up check comments as requiring a glyph, but if

you deploy the extension as it is right now you won’t see anything because there are no components

offering to draw a CheckCommentTag. For that you need a glyph factory, which is the other half of

the extension. Here is the code:

c#

using System.ComponentModel.Composition;

using System.Windows;

using System.Windows.Media;

using System.Windows.Shapes;

using Microsoft.VisualStudio.Text.Editor;

using Microsoft.VisualStudio.Text.Formatting;

using Microsoft.VisualStudio.Text.Tagging;

using Microsoft.VisualStudio.Utilities;

namespace CheckCommentHighlighter

{

class CheckCommentGlyphFactory : IGlyphFactory

{

public UIElement GenerateGlyph(IWpfTextViewLine line, IGlyphTag tag)

{

extending the editor .

1055

var validTag = tag as CheckCommentTag != null;

if (!validTag)

return null;

return new Polygon

{

Fill = Brushes.LightBlue,

Stroke = Brushes.DarkBlue,

StrokeThickness = 2,

Points = new PointCollection

{

new Point(0, 0),

new Point(16, 8),

new Point(0, 16)

}

};

}

}

[Export(typeof(IGlyphFactoryProvider))]

[TagType(typeof(CheckCommentTag))]

[Name("CheckCommentGlyph")]

[ContentType("code")]

[Order(After="VSTextMarker")]

class CheckCommentGlyphFactoryProvider : IGlyphFactoryProvider

{

public IGlyphFactory GetGlyphFactory(IWpfTextView view,

IWpfTextViewMargin margin)

{

return new CheckCommentGlyphFactory();

}

}

}

Code snippet CheckCommentHighlighter\CheckCommentGlyphFactory.cs

Vb

Imports System.ComponentModel.Composition

Imports System.Windows

Imports System.Windows.Media

Imports System.Windows.Shapes

Imports Microsoft.VisualStudio.Text.Editor

Imports Microsoft.VisualStudio.Text.Formatting

Imports Microsoft.VisualStudio.Text.Tagging

Imports Microsoft.VisualStudio.Utilities

Friend Class CheckCommentGlyphFactory

Implements IGlyphFactory

1056 .

chaPter 53 mAnAged exTenSibiliTy FrAmeWork (meF)

Public Function GenerateGlyph(ByVal line As IWpfTextViewLine,

ByVal tag As IGlyphTag) As UIElement Implements IGlyphFactory.GenerateGlyph

If tag Is Nothing OrElse Not (TypeOf tag Is CheckCommentTag) Then

Return Nothing

End If

Dim triangle As New System.Windows.Shapes.Polygon()

With triangle

.Fill = Brushes.LightBlue

.Stroke = Brushes.DarkBlue

.StrokeThickness = 2

.Points = New PointCollection()

With .Points

.Add(New Point(0, 0))

.Add(New Point(16, 8))

.Add(New Point(0, 16))

End With

End With

Return triangle

End Function

End Class

<Export(GetType(IGlyphFactoryProvider)), Name("CheckCommentGlyph"),

Order(After:="VsTextMarker"), ContentType("code"),

TagType(GetType(CheckCommentTag))>

Friend NotInheritable Class TodoGlyphFactoryProvider

Implements IGlyphFactoryProvider

Public Function GetGlyphFactory(

ByVal view As Microsoft.VisualStudio.Text.Editor.IWpfTextView,

ByVal margin As Microsoft.VisualStudio.Text.Editor.IWpfTextViewMargin)

As Microsoft.VisualStudio.Text.Editor.IGlyphFactory

Implements Microsoft.VisualStudio.Text.Editor.IGlyphFactoryProvider.GetGlyphFactory

Return New CheckCommentGlyphFactory()

End Function

End Class

Code snippet CheckCommentHighlighter\CheckCommentGlyphFactory.vb

Just as with the code to expose the check comment tagger to Visual Studio, two classes are at

work here: one class that actually creates glyphs and another class that provides instances of this

glyph factory to Visual Studio on demand. The CheckCommentGlyphFactory is very simple. It just

checks to ensure that the tag is of the correct type and then creates the visual element that is to

be displayed. This can be any WPF UIElement. In this implementation, it is a light blue triangle

pointing to the right with a dark blue border.

The second class is the actual gateway into Visual Studio. It is exported using the

IGlyphFactoryProvider contract, associated with a specific tag and content type. It also

specifies a name that makes it easier to identify. Finally, it specifies that it should be drawn after

items in the “VSTextMarker” layer, which means it will appear to be on top of items in this

summary .

1057

layer. The actual implementation of this class is a simple factory method for instances of the

CheckCommentGlyphFactory

class.

If you run this extension it will start up in the

Experimental Instance of Visual Studio. Load a code file

and add a comment that starts with Check: and a blue

triangle appears in the margin to the left as fiGure 53-3

in Figure 53-3.

suMMary

The Managed Extensibility Framework simplifies the process of creating extensible applications by

allowing you to think of your application as a collection of composable parts, each of which exposes

exports and requires imports. Extensions can be added to your application by creating appropriate

catalogs of parts and providing them to your composition container. MEF is able to cover a much

wider range of capabilities than those covered in this chapter. Be sure to check out the MEF

Programming Guide on http://mef.codeplex.com for more information.

Visual Studio 2010 is able to create a highly extensible run time by taking advantage of MEF. It

watches extensions for known exported contracts, which it will use when composing the new WPF

Editor control, allowing you to easily extend its behavior. In addition to this, Visual Studio exports

a number of services on well-known contracts that you can import for use in your extensions. For

more information about the new Visual Studio Editor and how to extend it using MEF, consult the

Visual Studio 2010 Editor topic on MSDN, which contains many examples of extensions.

PART XII

Visual studio ultimate

. Visual Studio Ultimate for Architects

. Visual Studio Ultimate for Developers

. Visual Studio Ultimate for Testers

. Team Foundation Server

: chaPter 54

: chaPter 55

: chaPter 56

: chaPter 57

54 54

Visual studio Ultimate

for architects

目录
设置
设置
阅读主题
字体风格
雅黑 宋体 楷书 卡通
字体大小
适中 偏大 超大
保存设置
恢复默认
手机
手机阅读
扫码获取链接,使用浏览器打开
书架同步,随时随地,手机阅读
首 页 < 上一章 章节列表 下一章 > 尾 页