2011-02-17 46 views
1

編碼器,我正在構建一個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

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

回答

1

如果我理解正確的話,你想要知道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發生。通過反射,代碼可以將其他代碼加載爲對象並查看它。你可以用例如代碼找出一個類有多少種方法,參數是什麼......並且一旦分析完畢,您可以調用這些方法。它使得一個非常強大的概念,因爲它允許代碼分析和重寫本身。或者編寫寫代碼的代碼。

1

這並非完全正確。 Visual Studio內置了對MEF的支持,Export Attribute只告訴VS這個類實現了IWpfTextViewCreationListener,並且它可以由VS導入。在後臺VS加載所有安裝在其中的軟件包,並將所有啓用了MEF的軟件包添加到其MEF容器中。

當打開一個編輯器時,VS會調用所有導入的IWpfTextViewCreationListener中具有相應ContentType集的TextViewCreated。

;)