Поделиться через


Добавление пользовательской проверки архитектуры в схемы слоев

В Visual Studio 2010 Ultimate и Visual Studio 2010 Premium пользователи могут проверять исходный код в проекте Visual Studio по модели слоев, чтобы убедиться, то исходный код соответствует зависимостям на схеме слоев. Несмотря на то что существует стандартный алгоритм проверки, данный пакет дополнительных компонентов Visual Studio 2010 позволяет определять собственные расширения проверки для Visual Studio Ultimate и Visual Studio Premium. Дополнительные сведения см. в разделе Пакеты функций Visual Studio.

Когда пользователь выбирает команду Проверить архитектуру на схеме слоев, вызывается стандартный метод проверки, за которым следуют установленные расширения проверки.

Примечание

Проверка на схеме слоев выполняется иначе, чем на UML-схемах.При работе со схемой слоев основной целью является сравнение схемы с программным кодом в других частях решения.

Расширение проверки слоев можно упаковать в формат Visual Studio Integration Extension (VSIX) и предоставить его другим пользователям Visual Studio Ultimate. Можно поместить в файл VSIX один проверяющий элемент управления или добавить в файл и другие расширения. Код проверяющего элемента управления необходимо создавать в отдельном проекте Visual Studio, а не в проекте, содержащем другие расширения.

Требования

Требования и инструкции по установке см. в подразделе Требования раздела Создание расширений для схем слоев.

Определение проверяющего элемента управления слоя в новом файле VSIX

Использование шаблона проекта — самый быстрый способ создания проверяющего элемента управления. В этом случае код и VSIX-манифест размещаются в одном и том же проекте.

Определения расширения с использованием шаблона проекта

  1. Создайте проект в новом решении, воспользовавшись командой Создать проект в меню Файл.

  2. В диалоговом окне Создать проект в разделе Проекты моделирования выберите Расширение проверки конструктора слоев.

    Шаблон создает проект, который содержит небольшой пример.

  3. Отредактируйте код, чтобы определить проверку. Дополнительные сведения см. в разделе Программная проверка.

  4. Сведения о тестировании расширения см. в разделе Отладка проверки слоев.

    Примечание

    Этот метод вызывается только в особых обстоятельствах, точки останова не срабатывают автоматически.Дополнительные сведения см. в разделе Отладка проверки слоев.

  5. Чтобы установить расширение в основном экземпляре Visual Studio или на другом компьютере, найдите файл .vsix в папке bin\*. Скопируйте его на компьютер, на котором его требуется установить, а затем дважды щелкните файл. Чтобы удалить его, выберите Диспетчер расширений в меню Сервис.

Добавление проверяющего элемента управления слоя в отдельный файл VSIX

Если требуется создать один VSIX-файл, который содержит проверяющие элементы слоев, команды и другие расширения, рекомендуется создать один проект для определения VSIX-файла и отдельный проект для обработчиков. Сведения о других типах расширения моделирования см. в разделе Расширение моделей и схем UML.

Добавление проверки слоев в отдельный файл VSIX

  1. Создайте проект библиотеки классов в новом или имеющемся решении Visual Studio Ultimate. В диалоговом окне Создать проект последовательно щелкните элементы Visual C# и Библиотека классов. Этот проект содержит класс проверки слоев.

  2. Определите или создайте в решении проект VSIX. Проект VSIX содержит файл с именем source.extension.vsixmanifest. Если необходимо добавить проект VSIX, выполните следующие действия:

    1. В диалоговом окне Создать проект разверните узел Visual C#, затем последовательно щелкните элементы Расширяемость и Проект VSIX.

    2. В обозревателе решений щелкните правой кнопкой мыши проект VSIX, затем выберите Назначить запускаемым проектом.

    3. Щелкните Выбрать выпуски и убедитесь, что Visual Studio Ultimate помечен флажком.

  3. В манифесте source.extension.vsixmanifest в разделе Содержание добавьте проект проверки слоев в качестве компонента MEF.

    1. Щелкните Добавить содержимое.

    2. В поле Выбор типа содержимого выберите MEF Component.

    3. В списке Выбор источника щелкните Проект и выберите имя проекта команд или обработчиков жестов.

    4. Сохраните файл.

  4. Добавьте проект проверки слоев в качестве пользовательского расширения:

    1. Щелкните Добавить содержимое.

    2. В поле Выбрать тип содержимого задайте значение Пользовательский тип расширения.

    3. В поле Тип укажите Microsoft.VisualStudio.ArchitectureTools.Layer.Validator.

    4. В списке Выбор источника щелкните Проект и выберите имя проекта библиотеки классов проверки.

  5. В разделе Ссылки щелкните Добавить ссылку и выберите среду выполнения для данного пакета дополнительных компонентов.

  6. Вернитесь в проект проверки слоев и добавьте следующие ссылки на проект:

    Ссылка

    Возможности

    Если установлен пакет дополнительных компонентов визуализации и моделирования Visual Studio 2010:

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

    Если установлен пакет дополнительных компонентов Visual Studio 2010 Feature Pack 2:

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

    Чтение графа архитектуры

    Если установлен пакет дополнительных компонентов визуализации и моделирования Visual Studio 2010:

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

    Если установлен пакет дополнительных компонентов Visual Studio 2010 Feature Pack 2:

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

    Чтение кода DOM, связанного со слоями

    Если установлен пакет дополнительных компонентов визуализации и моделирования Visual Studio 2010:

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

    Если установлен пакет дополнительных компонентов Visual Studio 2010 Feature Pack 2:

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

    Чтение модели слоев

    Microsoft.VisualStudio.Uml.Interfaces

    Чтение модели слоев

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Чтение и обновление фигур и схем

    System.ComponentModel.Composition

    Определение компонента проверки с использованием Managed Extensibility Framework (MEF)

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Определение расширений моделирования

    Примечание

    Обычно параметру %LocalAppData% соответствует путь имя_диска:\Users\имя_пользователя\AppData\Local.В Windows XP или Windows 2003 вместо %LocalAppData% следует использовать переменную %AppData%.

  7. Измените файл классов в проекте библиотеки классов C# таким образом, чтобы он содержал код проверки. Дополнительные сведения см. в разделе Программная проверка.

  8. Сведения о тестировании расширения см. в разделе Отладка проверки слоев.

    Примечание

    Этот метод вызывается только в особых обстоятельствах, точки останова не срабатывают автоматически.Дополнительные сведения см. в разделе Отладка проверки слоев.

  9. Чтобы установить VSIX в главном экземпляре Visual Studio или на другом компьютере, найдите файл .vsix в каталоге bin проекта VSIX. Скопируйте его на компьютер, на котором требуется установить VSIX. Дважды щелкните файл VSIX в проводнике Windows.

    Чтобы удалить его, выберите Диспетчер расширений в меню Сервис.

Программная проверка

Чтобы определить расширение проверки слоя, необходимо определить класс со следующими характеристиками:

  • Необходимо использовать следующую общую форму объявления:

      [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);
        }
    
  • При обнаружении ошибки сообщить о ней можно с использованием LogValidationError().

Когда пользователь вызывает команду меню Проверить архитектуру, система среды выполнения слоев анализирует слои и их артефакты для создания графа. Граф состоит из 4 частей:

  • Модели слоев решения Visual Studio, представленные на графе в виде узлов и связей.

  • Код, элементы проекта и другие артефакты, определенные в решении и представленные в виде узлов, а также связи, представляющие зависимости, которые были обнаружены в процессе анализа.

  • Связи между узлами слоя и узлами артефактов кода.

  • Узлы, представляющие ошибки, которые были обнаружены проверяющим элементом управления.

По завершении создания графа вызывается стандартный метод проверки. После этого все установленные методы проверки расширения вызываются в произвольном порядке. Граф передается каждому методу ValidateArchitecture, который может сканировать граф и сообщать о любых обнаруженных ошибках.

Примечание

При работе с UML-схемами и доменными языками используется другой процесс проверки.

Методы проверки не должны менять проверяемую модель слоев или код.

Модель графа определена в узле Microsoft.VisualStudio.GraphModel. Основными классами этого узла являются Node и Link.

Каждый узел и каждая связь имеют одну или несколько категорий, задающих тип элемента или отношения, которое этот узел или связь представляет. Узлы типичного графа имеют следующие категории:

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

Связи от слоев к элементам в коде имеют категорию "Представляет".

Следующий код является типичным примером расширения проверки архитектуры. Он позволяет проверить, что на каждый тип, объявленный в коде решения, имеется хотя бы одна ссылка в модели слоев. Пользователь может указать, нужно ли выполнять эту проверку в каждой модели слоев, задав логическое пользовательское свойство модели.

При обнаружении ошибки вызывается метод LogValidationError.

Отладка проверки

Чтобы выполнить отладку расширения проверки слоев, нажмите сочетание клавиш CTRL+F5. Откроется экспериментальный экземпляр Visual Studio. Откройте или создайте модель слоев в этом экземпляре. Эта модель должна быть связана с кодом и должна иметь хотя бы одну зависимость.

Тестирование решения, содержащего зависимости

Проверка выполняется только при наличии следующих характеристик:

  • В схеме слоев присутствует хотя бы одна связь зависимости.

  • В модели имеются слои, связанные с элементами кода.

При первом запуске экспериментального экземпляра Visual Studio для тестирования расширения проверки откройте или создайте решение с указанными характеристиками.

Выполнение очистки решения перед проверкой архитектуры

Всякий раз при обновлении кода проверки необходимо использовать команду Очистить решение в меню Построение экспериментального решения. Только после этого можно тестировать команду "Проверка". Это необходимо потому, что результаты проверки кэшируются. Если тестовая схема слоев или ее код не обновлялись, методы проверки не будут выполнены.

Явный запуск отладчика

Проверка выполняется отдельным процессом. Следовательно, точки останова используемого метода проверки не будут активированы. Необходимо явно прикрепить отладчик к процессу после запуска проверки.

Чтобы прикрепить отладчик к процессу проверки, вставьте вызов метода System.Diagnostics.Debugger.Launch() в начало метода проверки. Когда отобразится диалоговое окно отладки, выберите основной экземпляр Visual Studio.

Кроме того, можно вставить вызов метода System.Windows.Forms.MessageBox.Show(). Когда отобразится окно сообщений, перейдите к основному экземпляру Visual Studio и в меню Отладка щелкните Присоединение к процессу. Выберите процесс с именем Graphcmd.exe.

Всегда запускайте экспериментальный экземпляр, нажимая сочетание клавиш CTRL+F5 (Запуск без отладки).

Развертывание расширения проверки

Чтобы установить расширение проверки на компьютере, на котором установлена система Visual Studio Ultimate или Visual Studio Premium, откройте VSIX-файл на конечном компьютере. Чтобы установить расширение на компьютере, на котором установлено построение Team Foundation Build, необходимо вручную извлечь содержимое файла VSIX в папку "Расширения". Дополнительные сведения см. в разделе Развертывание расширения моделирования слоев.

Пример

В следующем примере продемонстрировано расширение проверки слоев.

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

См. также

Другие ресурсы

Создание расширений для схем слоев

Журнал изменений

Дата

Журнал

Причина

Декабрь 2010

Обновлено с учетом пакета дополнительных компонентов Visual Studio 2010 Feature Pack 2.

Улучшение информации.