Compartir a través de


Agregar validación de arquitectura personalizada a diagramas de capas

En Visual Studio 2010 Ultimate y Visual Studio 2010 Premium, los usuarios pueden validar el código fuente en un proyecto de Visual Studio con un modelo de capas para comprobar que el código fuente cumple las dependencias en un diagrama de capas. Hay un algoritmo de validación estándar, pero este Feature Pack de Visual Studio 2010 le permite definir sus propias extensiones de validación para Visual Studio Ultimate y Visual Studio Premium. Para obtener más información, vea Paquetes de características de Visual Studio.

Cuando el usuario selecciona el comando Validar arquitectura en un diagrama de capas, se invoca el método de validación estándar, seguido de cualquier extensión de validación que se haya instalado.

Nota

La validación en un diagrama de capas no es lo mismo que la validación en diagramas UML. En un diagrama de capas, el propósito principal es comparar el diagrama con el código de programa de otras partes de la solución.

Puede empaquetar la extensión de validación de capas en una extensión de integración de Visual Studio (VSIX), que puede distribuir a otros usuarios de Visual Studio Ultimate. Puede colocar el validador en VSIX por sí solo o puede combinarlo en el mismo VSIX con otras extensiones. Debe escribir el código del validador en su propio proyecto de Visual Studio, no en el mismo proyecto que otras extensiones.

Requisitos

Para obtener los requisitos e instrucciones de instalación, vea Requisitos en Crear extensiones de diagramas de capas.

Definir un validador de capas en un nuevo VSIX

El método más rápido para crear un validador consiste en usar la plantilla de proyecto. Esto coloca el código y el manifiesto de VSIX en el mismo proyecto.

Para definir una extensión mediante una plantilla de proyecto

  1. Cree un proyecto en una nueva solución mediante el comando Nuevo proyecto del menú Archivo.

  2. En el cuadro de diálogo Nuevo proyecto, en Proyectos de modelado, seleccione Layer Designer Validation Extension (Extensión de validación de diseñador de capas).

    La plantilla crea un proyecto que contiene un pequeño ejemplo.

  3. Modifique el código para definir la validación. Para obtener más información, vea Programar la validación.

  4. Para probar la extensión, vea Depurar la validación de capas.

    Nota

    Solo se llamará al método en circunstancias concretas y los puntos de interrupción no funcionarán automáticamente. Para obtener más información, vea Depurar la validación de capas.

  5. Para instalar la extensión en la instancia principal de Visual Studio o en otro equipo, busque el archivo .vsix en bin\*. Cópielo en el equipo donde desea instalarlo y, a continuación, haga doble clic en él. Para desinstalarlo, use el Administrador de extensiones en el menú Herramientas.

Agregar un validador de capas a un VSIX independiente

Si desea crear un VSIX que contenga validadores de capas, comandos y otras extensiones, le recomendamos que cree un proyecto para definir VSIX y proyectos independientes para los controladores. Para obtener información sobre otros tipos de extensión de modelado, vea Ampliar modelos y diagramas UML.

Para agregar la validación de capas a un VSIX independiente

  1. Cree un proyecto de biblioteca de clases en una solución de Visual Studio Ultimate nueva o en una existente. En el cuadro de diálogo Nuevo proyecto, haga clic en Visual C# y haga clic en Biblioteca de clases. Este proyecto contendrá la clase de validación de capas.

  2. Identifique o cree un proyecto de VSIX en la solución. Un proyecto de VSIX contiene un archivo denominado source.extension.vsixmanifest. Si tiene que agregar un proyecto VSIX, siga estos pasos:

    1. En el cuadro de diálogo Nuevo proyecto, expanda Visual C#, haga clic en Extensibility (Extensibilidad) y, a continuación, en VSIX Project (Proyecto de VSIX).

    2. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto de VSIX y, a continuación, haga clic en Establecer como proyecto de inicio.

    3. Haga clic en Select Editions (Seleccionar ediciones) y asegúrese de que Visual Studio Ultimate está activado.

  3. En source.extension.vsixmanifest, en Content (Contenido), agregue el proyecto de validación de capas como un componente MEF:

    1. Haga clic en Agregar contenido.

    2. En Seleccione un tipo de contenido, seleccione MEF Component.

    3. En Select a source (Seleccionar un origen), haga clic en Project (Proyecto) y seleccione el nombre del proyecto de controlador de comandos o de gestos.

    4. Guarde el archivo.

  4. Agregue el proyecto de validación de capas como una extensión personalizada:

    1. Haga clic en Agregar contenido.

    2. En Select a content type (Seleccione un tipo de contenido), elija Custom Extension Type (Tipo de extensión personalizada).

    3. En Type (Tipo), escriba Microsoft.VisualStudio.ArchitectureTools.Layer.Validator

    4. En Select a source (Seleccione un origen), haga clic en Project (Proyecto) y seleccione el nombre del proyecto de biblioteca de clases de validación.

  5. En References (Referencias) haga clic en Add Reference (Agregar referencia) y seleccione el motor en tiempo de ejecución de este Feature Pack.

  6. Vuelva al proyecto de validación de capas y agregue las siguientes referencias de proyecto:

    Referencia

    Qué permite hacer

    Si tiene instalado el Feature Pack de visualización y modelado de Visual Studio 2010:

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

    Si tiene instalado el Feature Pack 2 de Visual Studio 2010:

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

    Leer el gráfico de la arquitectura

    Si tiene instalado el Feature Pack de visualización y modelado de Visual Studio 2010:

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

    Si tiene instalado el Feature Pack 2 de Visual Studio 2010:

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

    Leer el código que DOM asoció a las capas

    Si tiene instalado el Feature Pack de visualización y modelado de Visual Studio 2010:

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

    Si tiene instalado el Feature Pack 2 de Visual Studio 2010:

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

    Leer el modelo de capas

    Microsoft.VisualStudio.Uml.Interfaces

    Leer el modelo de capas

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Leer y actualizar formas y diagramas.

    System.ComponentModel.Composition

    Definir el componente de validación mediante MEF (Managed Extensibility Framework)

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Definir las extensiones de modelado

    Nota

    %LocalAppData% está normalmente en DriveName:\Users\nombreDeUsuario\AppData\Local\. En Windows XP o Windows 2003, use %AppData% en lugar de %LocalAppData%.

  7. Edite el archivo de clases en el proyecto de biblioteca de clases de C# para que contenga el código de la validación. Para obtener más información, vea Programar la validación.

  8. Para probar la extensión, vea Depurar la validación de capas.

    Nota

    Solo se llamará al método en circunstancias concretas y los puntos de interrupción no funcionarán automáticamente. Para obtener más información, vea Depurar la validación de capas.

  9. Para instalar VSIX en la instancia principal de Visual Studio o en otro equipo, busque el archivo .vsix en el directorio bin del proyecto de VSIX. Cópielo en el equipo donde desea instalar VSIX. En el Explorador de Windows, haga doble clic en el archivo VSIX.

    Para desinstalarlo, use el Administrador de extensiones en el menú Herramientas.

Programar la validación

Para definir una extensión de validación de capas, defina una clase que tenga las siguientes características:

  • El formato general de la declaración será similar al siguiente:

      [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);
        }
    
  • Al detectar un error, puede notificarlo mediante LogValidationError().

Cuando el usuario invoca el comando de menú Validar arquitectura, el sistema en tiempo de ejecución de capas analiza las capas y sus artefactos para generar un gráfico. El gráfico tiene cuatro partes:

  • Los modelos de capas de la solución de Visual Studio que se representan como nodos y vínculos en el gráfico.

  • El código, los elementos de proyecto y otros artefactos definidos en la solución y representados como nodos, y los vínculos que representan las dependencias detectadas por el proceso de análisis.

  • Los vínculos de los nodos de capa a los nodos de artefacto de código.

  • Los nodos que representan los errores detectados por el validador.

Cuando se ha construido el gráfico, se llama al método de validación estándar. Una vez completado, se llama en un orden no especificado a los métodos de validación de extensiones instalados. El gráfico se pasa a cada método de ValidateArchitecture, que puede examinar el gráfico y notificar los errores que encuentre.

Nota

Esto no es igual que el proceso de validación que se aplica a los diagramas UML y no es igual que el proceso de validación que se puede usar en los lenguajes específicos del dominio.

Los métodos de validación no deben cambiar el modelo de capas ni el código que se valida.

El modelo del gráfico se define en Microsoft.VisualStudio.GraphModel. Sus clases principales son Node y Link.

Cada nodo y cada vínculo tiene una o más categorías que especifican el tipo de elemento o relación que representa. Los nodos de un gráfico típico tienen las siguientes categorías:

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

Los vínculos entre las capas y los elementos del código tienen la categoría "Representa".

El siguiente código es un ejemplo típico de una extensión de validación de arquitectura. Comprueba que el modelo de capas hace referencia al menos una vez a cada tipo declarado en el código de la solución. El usuario puede controlar si esta validación se debe realizar en cada modelo de capas si establece una propiedad personalizada booleana del modelo.

Si se produce un error, se llama a LogValidationError.

Depurar la validación

Para depurar la extensión de validación de capas, presione CTRL+F5. Se abre una instancia experimental de Visual Studio. En esta instancia, abra o cree un modelo de capas. Este modelo debe estar asociado a código y debe tener al menos una dependencia.

Probar con una solución que contiene dependencias

No se ejecuta la validación a menos que estén presentes las siguientes características:

  • Hay al menos un vínculo de dependencia en el diagrama de capas.

  • Hay capas del modelo asociadas a elementos de código.

La primera vez que inicia una instancia experimental de Visual Studio para probar la extensión de validación, debe abrir o crear una solución que tenga estas características.

Ejecutar Limpiar solución antes de validar la arquitectura

Cada vez que actualice el código de validación, use el comando Limpiar solución en el menú Generar de la solución experimental antes de probar el comando Validar. Esto es necesario porque los resultados de la validación se almacenan en memoria caché. Si no ha actualizado el diagrama de capas de pruebas ni el código, no se ejecutarán los métodos de validación.

Iniciar el depurador explícitamente

La validación se ejecuta en un proceso independiente. Por consiguiente, esos puntos de interrupción del método de validación no se activarán. Debe adjuntar explícitamente el depurador al proceso cuando se haya iniciado la validación.

Para adjuntar el depurador al proceso de validación, inserte una llamada a System.Diagnostics.Debugger.Launch() en el inicio del método de validación. Cuando aparezca el cuadro de diálogo de depuración, seleccione la instancia principal de Visual Studio.

Alternativamente, puede insertar una llamada a System.Windows.Forms.MessageBox.Show(). Cuando aparezca el cuadro de mensaje, vaya a la instancia principal de Visual Studio y, en el menú Depurar, haga clic en Asociar al proceso. Seleccione el proceso denominado Graphcmd.exe.

Inicie siempre la instancia experimental presionando CTRL+F5 (Iniciar sin depurar).

Implementar una extensión de validación

Para instalar la extensión de validación en un equipo en el que está instalado Visual Studio Ultimate o Visual Studio Premium, abra el archivo VSIX en el equipo de destino. Para instalarla en un equipo en el que está instalado Team Foundation Build, debe extraer manualmente el contenido de VSIX en una carpeta Extensions. Para obtener más información, vea Implementar una extensión de modelado de capas.

Ejemplo

En el siguiente ejemplo se muestra una extensión de validación de capas.

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;
  }
}

Vea también

Otros recursos

Crear extensiones de diagramas de capas

Historial de cambios

Fecha

Historial

Motivo

Diciembre de 2010

Actualizado para el Feature Pack 2 de Visual Studio 2010.

Mejora de la información.