Freigeben über


Hinzufügen einer benutzerdefinierten Architekturüberprüfung zu Ebenendiagrammen

In Visual Studio 2010 Ultimate und Visual Studio 2010 Premium können Benutzer den Quellcode in einem Visual Studio-Projekt anhand eines Ebenenmodells überprüfen. So kann festgestellt werden, ob der Quellcode den Abhängigkeiten in einem Ebenendiagramm entspricht. Es gibt zwar einen Standardvalidierungsalgorithmus, doch können Sie mit diesem Visual Studio 2010 Feature Pack eigene Validierungserweiterungen für Visual Studio Ultimate und Visual Studio Premium definieren. Weitere Informationen finden Sie unter Visual Studio Feature Packs.

Wenn der Benutzer den Befehl Architektur überprüfen für ein Ebenendiagramm auswählt, wird die Standardvalidierungsmethode aufgerufen, anschließend folgen alle installierten Validierungserweiterungen.

Tipp

Die Validierung in einem Ebenendiagramm ist nicht mit einer Validierung in UML-Diagrammen vergleichbar. In einem Ebenendiagramm dient sie hauptsächlich dazu, das Diagramm mit dem Programmcode in anderen Teilen der Projektmappe zu vergleichen.

Sie können die Ebenenvalidierungserweiterung in eine Visual Studio-Integrationserweiterung (VSIX) verpacken, die Sie an andere Visual Studio Ultimate-Benutzer verteilen. Sie können entweder das Validierungssteuerelement allein in eine VSIX einfügen, oder Sie können es in der gleichen VSIX mit anderen Erweiterungen kombinieren. Schreiben Sie den Code für das Validierungssteuerelement in einem eigenen Visual Studio-Projekt und nicht im gleichen Projekt wie andere Erweiterungen.

Anforderungen

Anforderungen und Installationsanweisungen finden Sie unter Anforderungen in Erstellen von Erweiterungen für Ebenendiagramme.

Definieren eines Ebenenvalidierungssteuerelements in einer neuen VSIX

Projektvorlagen stellen die schnellste Methode dar, eine Validierungssteuerelement zu erstellen. Dabei werden der Code und die VSIX im selben Projekt platziert.

So definieren Sie mithilfe einer Projektvorlage eine Erweiterung

  1. Erstellen Sie in einer neuen Projektmappe ein Projekt. Verwenden Sie dazu den Befehl Neues Projekt im Menü Datei.

  2. Klicken Sie im Dialogfeld Neues Projekt unter Modellierungsprojekte auf Layer Designer Validation Extension (Ebenen-Designer - Validierungserweiterung).

    Mit dieser Vorlage wird ein Projekt mit einem kleinen Beispiel erstellt.

  3. Bearbeiten Sie den Code, um die Validierung zu definieren. Weitere Informationen finden Sie unter Programmieren einer Validierung.

  4. Weitere Informationen zum Testen der Erweiterung finden Sie unter Debuggen der Ebenenvalidierung.

    Tipp

    Die Methode wird nur unter bestimmten Umständen aufgerufen, und Haltepunkte funktionieren nicht automatisch. Weitere Informationen finden Sie unter Debuggen der Ebenenvalidierung.

  5. Um die Erweiterung in der Hauptinstanz von Visual Studio oder auf einem anderen Computer zu installieren, suchen Sie die Datei .vsix im Ordner bin\*. Kopieren Sie die Datei auf den Computer, auf dem Sie sie installieren möchten, und doppelklicken Sie dann darauf. Verwenden Sie Erweiterungs-Manager im Menü Extras zum Deinstallieren der Datei.

Hinzufügen eines Ebenenvalidierungssteuerelements zu einer separaten VSIX

Wenn Sie eine VSIX erstellen möchten, die Ebenenvalidierungssteuerelemente, Befehle und andere Erweiterungen enthält, empfiehlt es sich, ein Projekt zum Definieren der VSIX und getrennte Projekte für die Handler zu erstellen. Informationen zu anderen Modellerweiterungstypen finden Sie unter Erweitern von UML-Modellen und Diagrammen.

So fügen Sie einer separaten VSIX eine Ebenenvalidierung hinzu

  1. Erstellen Sie in einer neuen oder vorhandenen Visual Studio Ultimate-Projektmappe ein Klassenbibliotheksprojekt. Klicken Sie im Dialogfeld Neues Projekt auf Visual C#, und klicken Sie dann auf Klassenbibliothek. Dieses Projekt enthält die Ebenenvalidierungsklasse.

  2. Identifizieren oder erstellen Sie ein VSIX-Projekt in der Projektmappe. Ein VSIX-Projekt enthält eine Datei mit dem Namen source.extension.vsixmanifest. Wenn Sie ein VSIX-Projekt hinzufügen müssen, führen Sie die folgenden Schritte aus:

    1. Erweitern Sie im Dialogfeld Neues Projekt den Knoten Visual C#, und klicken Sie auf Erweiterungen und anschließend auf VSIX Project.

    2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das VSIX-Projekt, und klicken Sie anschließend auf Als Startprojekt festlegen.

    3. Klicken Sie auf Editionen auswählen, und stellen Sie sicher, dass Visual Studio Ultimate überprüft wird.

  3. Fügen Sie in source.extension.vsixmanifest unter Inhalt das Ebenenvalidierungsprojekt als MEF-Komponente hinzu:

    1. Klicken Sie auf Inhalt hinzufügen.

    2. Wählen Sie für Inhaltstyp auswählen die Option MEF-Komponente aus.

    3. Klicken Sie in Quelle auswählen auf Projekt, und wählen Sie den Namen des Befehls- oder Gestenhandlerprojekts aus.

    4. Speichern Sie die Datei.

  4. Fügen Sie das Ebenenvalidierungsprojekt als benutzerdefinierte Erweiterung hinzu:

    1. Klicken Sie auf Inhalt hinzufügen.

    2. Wählen Sie unter Inhaltstyp auswählen die Option Benutzerdefinierter Erweiterungstyp aus.

    3. Geben Sie unter Typ den Text Microsoft.VisualStudio.ArchitectureTools.Layer.Validator ein.

    4. Klicken Sie in Quelle auswählen auf Projekt, und wählen Sie den Namen des Validierungs-Klassenbibliotheksprojekts aus.

  5. Klicken Sie unter Verweise auf Verweis hinzufügen, und wählen Sie die Laufzeit für dieses Feature Pack aus.

  6. Kehren Sie zum Ebenenvalidierungsprojekt zurück, und fügen Sie die folgenden Projektverweise hinzu:

    Verweise

    Optionen

    Wenn Sie Visual Studio 2010 Visualization and Modeling Feature Pack installiert haben:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.GraphModel.dll

    Wenn Sie Visual Studio 2010 Feature Pack 2 installiert haben:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.GraphModel.dll

    Lesen des Architekturdiagramms

    Wenn Sie Visual Studio 2010 Visualization and Modeling Feature Pack installiert haben:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll

    Wenn Sie Visual Studio 2010 Feature Pack 2 installiert haben:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\ Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll

    Lesen des Ebenen zugeordneten Code-DOMs

    Wenn Sie Visual Studio 2010 Visualization and Modeling Feature Pack installiert haben:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll

    Wenn Sie Visual Studio 2010 Feature Pack 2 installiert haben:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll

    Lesen des Ebenenmodells

    Microsoft.VisualStudio.Uml.Interfaces

    Lesen des Ebenenmodells

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Lesen und Aktualisieren von Formen und Diagrammen.

    System.ComponentModel.Composition

    Definieren der Validierungskomponente mithilfe von Managed Extensibility Framework (MEF)

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Definieren von Modellierungserweiterungen

    Tipp

    %LocalAppData% ist in der Regel DriveName:\Users\UserName\AppData\Local. Verwenden Sie unter Windows XP oder Windows 2003 %APPDATA% statt %LocalAppData%.

  7. Bearbeiten Sie die Klassendatei im C#-Klassenbibliotheksprojekt so, dass sie den Code für die Validierung enthält. Weitere Informationen finden Sie unter Programmieren einer Validierung.

  8. Weitere Informationen zum Testen der Erweiterung finden Sie unter Debuggen der Ebenenvalidierung.

    Tipp

    Die Methode wird nur unter bestimmten Umständen aufgerufen, und Haltepunkte funktionieren nicht automatisch. Weitere Informationen finden Sie unter Debuggen der Ebenenvalidierung.

  9. Um die Erweiterung in der Hauptinstanz von Visual Studio oder auf einem anderen Computer zu installieren, suchen Sie die Datei .vsix im Verzeichnis bin des VSIX-Projekts. Kopieren Sie die Datei auf den Computer, auf dem Sie die VSIX installieren möchten. Doppelklicken Sie in Windows-Explorer auf die VSIX-Datei.

    Verwenden Sie Erweiterungs-Manager im Menü Extras zum Deinstallieren der Datei.

Programmieren einer Validierung

Zum Definieren einer Ebenenvalidierungserweiterung definieren Sie eine Klasse, die über die folgenden Eigenschaften verfügt:

  • Die allgemeine Form der Deklaration lautet wie folgt:

      [Export(typeof(IValidateArchitectureExtension))]
      public partial class Validator1Extension :
                      IValidateArchitectureExtension
      {
        public void ValidateArchitecture(Graph graph)
        {
          var typeCategory = graph.DocumentSchema
                     .Categories.Get("CodeSchema_Type");
          var allTypes = graph.Nodes.GetByCategory(typeCategory);
        ...
          this.LogValidationError(graph, "SampleErrorId", 
             "Sample Validation Error", GraphErrorLevel.Error, allTypes);
        }
    
  • Wenn Sie einen Fehler entdecken, können Sie ihn mit LogValidationError() melden.

Wenn der Benutzer den Menübefehl Architektur überprüfen aufruft, werden die Ebenen und ihre Artefakte vom Ebenenlaufzeitsystem analysiert, und es wird ein Diagramm erstellt. Das Diagramm besteht aus vier Teilen:

  • Den Ebenenmodellen der Visual Studio-Projektmappe, die als Knoten und Links im Diagramm dargestellt werden.

  • Dem Code, Projektelementen und anderen Artefakte, die in der Projektmappe definiert und als Knoten dargestellt werden, sowie den Links, die die vom Analyseprozess ermittelten Abhängigkeiten vertreten.

  • Links von den Ebenenknoten zu den Codeartefaktknoten.

  • Knoten, die die vom Validierungssteuerelement ermittelten Fehler darstellen.

Wenn das Diagramm erstellt wurde, wird die Standardvalidierungsmethode aufgerufen. Nachdem diese abgeschlossen ist, werden alle installierten Erweiterungsvalidierungsmethoden ohne spezifische Reihenfolge aufgerufen. Das Diagramm wird an jede ValidateArchitecture-Methode übergeben, die das Diagramm überprüfen und gefundene Fehler melden kann.

Tipp

Dies ist nicht mit dem Validierungsprozess gleichzusetzen, der auf UML-Diagramme angewendet wird und auch nicht mit dem Validierungsprozess, der bei domänenspezifischen Sprachen verwendet werden kann.

Validierungsmethoden sollten das zu überprüfende Ebenenmodell oder den Code nicht ändern.

Das Diagrammmodell wird in Microsoft.VisualStudio.GraphModel definiert. Seine Prinzipalklassen sind Node und Link.

Jeder Knoten und jeder Link verfügt über mindestens eine Kategorie, die den Typ des Elements oder der Beziehung angibt, die von ihr dargestellt wird. Die Knoten eines typischen Diagramms verfügen über die folgenden Kategorien:

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

Links von Ebenen zu Elementen im Code haben die Kategorie "Represents".

Der folgende Code ist ein typisches Beispiel für eine Architekturvalidierungserweiterung. Es wird überprüft, ob vom Ebenenmodell mindestens einmal auf jeden im Code für die Projektmappe deklarierten Typ verwiesen wird. Der Benutzer kann steuern, ob diese Validierung für jedes Ebenenmodell ausgeführt werden soll, indem eine benutzerdefinierte boolesche Eigenschaft des Modells festgelegt wird.

Wenn kein Fehler gefunden wird, wird LogValidationError aufgerufen.

Debuggen der Validierung

Drücken Sie STRG+F5, um die Ebenenvalidierungserweiterung zu debuggen. Eine experimentelle Instanz von Visual Studio wird geöffnet. Öffnen oder erstellen Sie ein Ebenenmodell in dieser Instanz. Dieses Modell muss Code zugeordnet sein und muss mindestens eine Abhängigkeit besitzen.

Test mit einer Projektmappe, die Abhängigkeiten enthält

Die Validierung wird erst ausgeführt, wenn die folgenden Eigenschaften vorhanden sind:

  • Es gibt mindestens einen Abhängigkeitslink im Ebenendiagramm.

  • Es gibt Ebenen im Modell, die Codeelementen zugeordnet sind.

Öffnen oder erstellen Sie eine Projektmappe mit diesen Eigenschaften, wenn Sie eine experimentelle Instanz von Visual Studio zum ersten Mal zum Testen der Validierungserweiterung starten.

Ausführen einer Projektmappenbereinigung vor dem Überprüfen der Architektur

Verwenden Sie bei jeder Aktualisierung des Validierungscodes im Menü Erstellen der experimentellen Instanz den Befehl Projektmappe bereinigen, bevor Sie den Befehl "Überprüfen" testen. Dies ist notwendig, da die Ergebnisse der Validierung zwischengespeichert werden. Wenn das Testebenendiagramm oder sein Code nicht aktualisiert wurden, werden die Validierungsmethoden nicht ausgeführt.

Explizites Starten des Debuggers

Die Validierung wird in einem separaten Prozess ausgeführt. Folglich werden die Haltepunkte in der Validierungsmethode nicht ausgelöst. Sie müssen den Debugger explizit dem Prozess anfügen, wenn die Validierung gestartet wurde.

Fügen Sie am Anfang der Validierungsmethode einen Aufruf von System.Diagnostics.Debugger.Launch() ein, um den Debugger dem Validierungsprozess anzufügen. Wenn das Debugdialogfeld angezeigt wird, wählen Sie die Hauptinstanz von Visual Studio aus.

Alternativ können Sie einen Aufruf von System.Windows.Forms.MessageBox.Show() einfügen. Wenn das Meldungsfeld angezeigt wird, wechseln Sie zur Hauptinstanz von Visual Studio, und klicken Sie im Menü Debuggen auf An den Prozess anhängen. Wählen Sie den Prozess mit dem Namen Graphcmd.exe aus.

Starten Sie die experimentelle Instanz immer mit STRG+F5 (Starten ohne Debugging).

Bereitstellen einer Validierungserweiterung

Öffnen Sie die VSIX-Datei auf dem Zielcomputer, um die Validierungserweiterung auf einem Computer zu installieren, auf dem Visual Studio Ultimate oder Visual Studio Premium installiert ist. Um die Installation auf einem Computer mit Team Foundation Build auszuführen, müssen Sie den VSIX-Inhalt manuell in einen Ordner "Extensions" extrahieren. Weitere Informationen finden Sie unter Bereitstellen einer Ebenenmodellierungserweiterung.

Beispiel

Im folgenden Beispiel wird eine Ebenenvalidierungserweiterung veranschaulicht.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;

using Microsoft.VisualStudio.GraphModel;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;

namespace MyValidationExtensions
{ // This attribute identifies a layer validator:
  [Export(typeof(IValidateArchitectureExtension))]
  public partial class UnreferencedTypeValidatorExtension 
      : IValidateArchitectureExtension
  {
    private GraphCategory typeCategory = null;
    /// <summary>
    /// Validate the architecture
    /// </summary>
    /// <param name="graph">The graph</param>
    public void ValidateArchitecture(Graph graph)
    {
      // A good place to attach a debugger
      // System.Windows.Forms.MessageBox.Show("Attach - Unreferenced Type Validator");
      // To find the nodes that represent the code and the layers,
      // we need to filter by category.
      // Categories are identified by specific strings:
      if (typeCategory == null)
      {
        typeCategory = 
          graph.DocumentSchema.Categories.Get("CodeSchema_Type");
      }
      var layerModelCategory = 
        graph.DocumentSchema.Categories.Get("Dsl.LayerModel");
      var allLayerModels =
        graph.Nodes.GetByCategory(layerModelCategory);

      foreach (var layerModel in allLayerModels)
      {
        var allTypesMustBeReferencedProperty =
           ExtractProperty(layerModel, 
            AllTypesMustBeReferencedProperty.FullName);
        bool shouldAllTypesBeReferenced = 
          allTypesMustBeReferencedProperty == null 
          ? false 
          : Convert.ToBoolean(allTypesMustBeReferencedProperty);

        if (shouldAllTypesBeReferenced)
        {
          // Find all types referenced by layers:
          var referencedTypes = new HashSet<Node>();
          GetReferencedTypes(referencedTypes, layerModel);
          var allTypes = graph.Nodes.GetByCategory(typeCategory);

          foreach (var type in allTypes)
          {
            if (!referencedTypes.Contains(type))
            {
              // Filter out types that are not part of any 
              // assembly (for example referenced external types).
              if (type.GetContainmentSources(graph)
                .Where(n => n.HasCategory(graph.DocumentSchema
                .Categories.Get("CodeSchema_Assembly"))).Any())
              {
                // type is not referenced in the layer diagram
                this.LogValidationError(graph,
                    string.Format("{0}_UnreferencedTypeError_{1}",
                    GetFullyQualifiedTypeName(type), Guid.NewGuid()),
                    string.Format("AV1002 : Unreferenced type :"
                      + " {0}{2}Layer Diagram: {1}.layerdiagram.",
                        GetFullyQualifiedTypeName(type),
                        layerModel.Label,
                        Environment.NewLine),
                    GraphErrorLevel.Error,
                    new Node[] { type });
              }
            }
          }
        }
      }
    }

    private void GetReferencedTypes(HashSet<Node> referencedTypes, Node node)
    {
      foreach (Node containedNode in node.GetContainmentTargets(node.Owner))
      {
        if (referencedTypes.Contains(containedNode))
        {
          // We've seen this node before
          continue;
        }

        if (containedNode.HasCategory(typeCategory))
        {
          referencedTypes.Add(containedNode);
        }
        else
        {
          GetReferencedTypes(referencedTypes, containedNode);
        }
      }
    }
    public static string GetFullyQualifiedTypeName(Node typeNode)
    {
      try
      {
         string returnValue;
         CodeQualifiedIdentifierBuilder id = 
           new CodeQualifiedIdentifierBuilder(
                   typeNode.Id, typeNode.Owner);
         returnValue = id.GetFullyQualifiedLabel(
              CodeQualifiedIdentifierBuilder.LabelFormat
              .NoAssemblyPrefix);
        return returnValue;
      }
      catch { }
     return typeNode.Label;
  }

  public static object ExtractProperty
             (Node layerModel, string propertyName)
  {
    object propertyValue = null;
    var propertyCategory = 
        layerModel.Owner.DocumentSchema.GetProperty(propertyName);
    if (propertyCategory != null)
    {
      propertyValue = layerModel[propertyCategory];
    }
    return propertyValue;
  }
}

Siehe auch

Weitere Ressourcen

Erstellen von Erweiterungen für Ebenendiagramme

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Dezember 2010

Aktualisiert für Visual Studio 2010 Feature Pack 2.

Informationsergänzung.