向我解释以下VS 2010扩展示例代码

问题描述:

编码器,我正在构建一个VS 2010扩展,并且我正在尝试VS 2010 SDK附带的一些示例。向我解释以下VS 2010扩展示例代码

其中一个示例项目称为TextAdornment。在该项目中有一个怪人类,如下所示:

[Export(typeof(IWpfTextViewCreationListener))] 
[ContentType("text")] 
[TextViewRole(PredefinedTextViewRoles.Document)] 
internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener 

当我和这个项目的实验,我试图调试项目,看看该程序的流量,我注意到,这个类被击中当我第一次开始调试。

现在我的问题如下:是什么让这个类成为VS启动时调用的第一个类?换句话说,为什么这个类变得活跃,并且它在一些代码中运行时实例化了这个类类型的对象?

下面是示例项目中仅有的两个文件:

TextAdornment1Factory.cs

using System.ComponentModel.Composition; 
using Microsoft.VisualStudio.Text.Editor; 
using Microsoft.VisualStudio.Utilities; 

namespace TextAdornment1 
{ 
    #region Adornment Factory 
    /// <summary> 
    /// Establishes an <see cref="IAdornmentLayer"/> to place the adornment on and exports the <see cref="IWpfTextViewCreationListener"/> 
    /// that instantiates the adornment on the event of a <see cref="IWpfTextView"/>'s creation 
    /// </summary> 
    [Export(typeof(IWpfTextViewCreationListener))] 
    [ContentType("text")] 
    [TextViewRole(PredefinedTextViewRoles.Document)] 
    internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener 
    { 
     /// <summary> 
     /// Defines the adornment layer for the adornment. This layer is ordered 
     /// after the selection layer in the Z-order 
     /// </summary> 
     [Export(typeof(AdornmentLayerDefinition))] 
     [Name("TextAdornment1")] 
     [Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)] 
     [TextViewRole(PredefinedTextViewRoles.Document)] 
     public AdornmentLayerDefinition editorAdornmentLayer = null; 

     /// <summary> 
     /// Instantiates a TextAdornment1 manager when a textView is created. 
     /// </summary> 
     /// <param name="textView">The <see cref="IWpfTextView"/> upon which the adornment should be placed</param> 
     public void TextViewCreated(IWpfTextView textView) 
     { 
      new TextAdornment1(textView); 
     } 
    } 
    #endregion //Adornment Factory 
} 

TextAdornment1.cs

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 
using Microsoft.VisualStudio.Text; 
using Microsoft.VisualStudio.Text.Editor; 
using Microsoft.VisualStudio.Text.Formatting; 

namespace TextAdornment1 
{ 
    ///<summary> 
    ///TextAdornment1 places red boxes behind all the "A"s in the editor window 
    ///</summary> 
    public class TextAdornment1 
    { 
     IAdornmentLayer _layer; 
     IWpfTextView _view; 
     Brush _brush; 
     Pen _pen; 

     ITextView textView; 

     public TextAdornment1(IWpfTextView view) 
     { 
      _view = view; 
      _layer = view.GetAdornmentLayer("TextAdornment1"); 
      textView = view; 

      //Listen to any event that changes the layout (text changes, scrolling, etc) 
      _view.LayoutChanged += OnLayoutChanged; 
      _view.Closed += new System.EventHandler(_view_Closed); 
      //selectedText(); 

      //Create the pen and brush to color the box behind the a's 
      Brush brush = new SolidColorBrush(Color.FromArgb(0x20, 0x00, 0x00, 0xff)); 
      brush.Freeze(); 
      Brush penBrush = new SolidColorBrush(Colors.Red); 
      penBrush.Freeze(); 
      Pen pen = new Pen(penBrush, 0.5); 
      pen.Freeze(); 

      _brush = brush; 
      _pen = pen; 
     } 

     void _view_Closed(object sender, System.EventArgs e) 
     { 
      MessageBox.Show(textView.Selection.IsEmpty.ToString()); 
     } 

     /// <summary> 
     /// On layout change add the adornment to any reformatted lines 
     /// </summary> 
     private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) 
     { 
      foreach (ITextViewLine line in e.NewOrReformattedLines) 
      { 
       this.CreateVisuals(line); 
      } 
     } 

     private void selectedText() 
     { 

     } 
     /// <summary> 
     /// Within the given line add the scarlet box behind the a 
     /// </summary> 
     private void CreateVisuals(ITextViewLine line) 
     { 
      //grab a reference to the lines in the current TextView 
      IWpfTextViewLineCollection textViewLines = _view.TextViewLines; 
      int start = line.Start; 
      int end = line.End; 

      //Loop through each character, and place a box around any a 
      for (int i = start; (i < end); ++i) 
      { 
       if (_view.TextSnapshot[i] == 'a') 
       { 
        SnapshotSpan span = new SnapshotSpan(_view.TextSnapshot, Span.FromBounds(i, i + 1)); 
        Geometry g = textViewLines.GetMarkerGeometry(span); 
        if (g != null) 
        { 
         GeometryDrawing drawing = new GeometryDrawing(_brush, _pen, g); 
         drawing.Freeze(); 

         DrawingImage drawingImage = new DrawingImage(drawing); 
         drawingImage.Freeze(); 

         Image image = new Image(); 
         image.Source = drawingImage; 

         //Align the image with the top of the bounds of the text geometry 
         Canvas.SetLeft(image, g.Bounds.Left); 
         Canvas.SetTop(image, g.Bounds.Top); 

         _layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, image, null); 
        } 
       } 
      } 
     } 
    } 
} 
+0

抱歉,家伙,*的代码渲染似乎不工作得很好! – ealshabaan 2011-02-17 07:25:38

如果我理解正确的话,你想要知道TextViewCreated(IWpfTextView textView)中textview的值在哪里从。由于这是一个示例项目VS插件,它在编辑器窗口的所有A中绘制红色框,我怀疑textview是一个指向VS的编辑器窗口的变量(或VS本身的某种对象,它将自己应用于所有在VS中适合的窗口,以便所有窗口都在它们的A之下有红色框)。

现在,如果您调试了示例项目,VS将加载插件并将调用TextViewCreated(IWpfTextView textView)来应用该插件。因为调试器只会停止在您的示例项目中的代码,而不是在VS本身的代码中,这是第一个被命中的类。这不是正在执行的第一类。这是VS的主要类别。现在

,你这称为怪人类:

[Export(typeof(IWpfTextViewCreationListener))] 
[ContentType("text")] 
[TextViewRole(PredefinedTextViewRoles.Document)] 
internal sealed class TextAdornment1Factory : IWpfTextViewCreationListener 

所以我怀疑,你是不熟悉如何在VS插件系统通常工作。插件通常是一类(或多个类),其中有一堆attributes(这就是[Export(typeof(IWpfTextViewCreationListener))],[ContentType("text")][TextViewRole(PredefinedTextViewRoles.Document)])。他们定义元数据(即关于类本身的数据)。他们告诉VS这个类是什么(即插件)。例如,Export(typeof(IWpfTextViewCreationListener)export attribute,并告诉VS类TextAdornment1Factory应该实例化为IWpfTextViewCreationListener类,而不是TextAdornment1Factory类。

如果你看看例如WPF,属性实际上到处都是。我曾经自己使用它们来编写验证框架。这使得添加/删除验证规则变得非常简单快捷,并且使得这些类非常易读,因为所有执行繁重代码的代码都被隐藏在另一个类中。您只能看到[TextLength(min=5, max=10]等属性。

现在,如果您想知道VS如何读取属性,那么通过reflection发生。通过反射,代码可以将其他代码加载为对象并查看它。你可以用例如代码找出一个类有多少种方法,参数是什么......并且一旦分析完毕,您可以调用这些方法。它使得一个非常强大的概念,因为它允许代码分析和重写本身。或者编写写代码的代码。

这并非完全正确。 Visual Studio内置了对MEF的支持,Export Attribute只告诉VS这个类实现了IWpfTextViewCreationListener,并且它可以由VS导入。在后台VS加载所有安装在其中的软件包,并将所有启用了MEF的软件包添加到其MEF容器中。

当打开一个编辑器时,VS会调用所有导入的IWpfTextViewCreationListener中具有相应ContentType集的TextViewCreated。

;)