向层关系图添加自定义体系结构验证

在 Visual Studio 旗舰版和 Visual Studio 高级专业版中,用户可以参照层模型验证 Visual Studio 项目中的源代码,以便可以验证源代码是否符合层关系图上的依赖项。 有一种标准验证算法,但是,您可以定义自己 Visual Studio 旗舰版 和 Visual Studio 高级专业版自己的验证扩展。

当用户在层关系图上选择**“验证体系结构”**命令时,将调用标准验证方法,并后跟已安装的任何验证扩展。

备注

层关系图中的验证与 UML 关系图中的验证不相同。在层关系图中,主要目的是将关系图与解决方案其他部分中的程序代码进行比较。

您可以将层验证扩展打包到一个 Visual Studio 集成扩展 (VSIX) 中,并可以将其分发给其他 Visual Studio 旗舰版用户。 您可以将验证程序单独放入一个 VSIX 中,也可以将其合并到其他扩展所在的同一个 VSIX 中。 您应在验证程序自己的 Visual Studio 项目中编写验证程序代码,而不是在其他扩展所在的同一项目中编写验证程序代码。

警告

在创建了一个验证项目后,请复制 代码示例 本主题末尾的然后编辑该到您的需要。

要求

  • Visual Studio 旗舰版

  • Visual Studio SDK

  • Visual Studio 可视化和建模 SDK

在新的 VSIX 中定义层验证程序

创建验证程序的最快速方法是使用项目模板。 这会将代码和 VSIX 清单放入同一个项目中。

使用项目模板定义扩展

  1. 通过使用**“文件”菜单上的“新建项目”**命令,在新解决方案中创建项目。

  2. 在**“新建项目”对话框中的“建模项目”下,选择“层设计器验证扩展”[Layer Designer Validation Extension]**。

    此模板将创建一个包含小示例的项目。

    警告

    使模板正常工作:

    • 编辑调用 LogValidationError 移除可选参数 errorSourceNodes 和 errorTargetNodes。

    • 如果您使用自定义特性,请将 向层关系图添加自定义属性提到的更新。此外,打开体系结构资源管理器中,在打开一个模型解决方案。

  3. 编辑代码以定义验证。 有关更多信息,请参见编程验证。

  4. 若要测试扩展,请参见调试层验证。

    备注

    仅在特定情形下才调用您的方法,而且断点不会自动工作。有关更多信息,请参见调试层验证。

  5. 若要在 Visual Studio 的主实例中或在其他计算机上安装扩展,请在 bin\* 中找到 .vsix 文件。 将该文件复制到要安装它的计算机中,然后双击它。 若要卸载该文件,请使用**“工具”菜单上的“扩展管理器”**。

将层验证程序添加到单独的 VSIX 中

若要创建一个包含层验证程序、命令和其他扩展的 VSIX,建议您创建一个项目来定义该 VSIX,并为处理程序创建单独的项目。 有关其他类型的建模扩展的信息,请参见扩展 UML 模型和关系图

将层验证添加到单独的 VSIX 中

  1. 在新的或现有的 Visual Studio 旗舰版解决方案中创建类库项目。 在**“新建项目”对话框中,单击“Visual C#”,再单击“类库”**。 此项目将包含层验证类。

  2. 在您的解决方案中标识或创建 VSIX 项目。 VSIX 项目包含一个名为 source.extension.vsixmanifest 的文件。 如果必须添加一个 VSIX 项目,请按照以下步骤操作:

    1. 新建项目 对话框中,选择 Visual C#扩展性VSIX 项目

    2. 解决方案资源管理器,在 VSIX 项目的快捷菜单,设为启动项目

  3. source.extension.vsixmanifest,在 资产下,将层验证项目添加为 MEF 组件:

    1. 单击**“新建”**。

    2. 添加新资产 对话框中,设置:

      类型 = Microsoft.VisualStudio.MefComponent

      = 当前解决方案中的项目

      项目 = 可以将验证程序项目

  4. 您还必须将它作为层验证:

    1. 单击**“新建”**。

    2. 添加新资产 对话框中,设置:

      类型 = Microsoft.VisualStudio.ArchitectureTools.Layer.Validator。 这不是一个在的选项卡下拉列表。 必须从键盘输入到。

      = 当前解决方案中的项目

      项目 = 可以将验证程序项目

  5. 返回到层验证项目,并添加以下项目引用:

    引用

    可完成的操作

    Microsoft.VisualStudio.GraphModel.dll

    读取体系结构关系图

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll

    读取与层关联的代码 DOM

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll

    读取层模型

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    读取和更新形状和关系图。

    System.ComponentModel.Composition

    使用 Managed Extensibility Framework (MEF) 定义验证组件

    Microsoft.VisualStudio.Modeling.Sdk.11.0

    定义建模扩展

  6. 复制示例代码本主题末尾到验证程序库项目的选件类文件以包含验证的代码。 有关更多信息,请参见编程验证。

  7. 若要测试扩展,请参见调试层验证。

    备注

    仅在特定情形下才调用您的方法,而且断点不会自动工作。有关更多信息,请参见调试层验证。

  8. 若要在 Visual Studio 的主实例中或其他计算机上安装 VSIX,请在 VSIX 项目的 bin 目录中找到 .vsix 文件。 将该文件复制到要安装 VSIX 的计算机中。 在 Windows 资源管理器中双击 VSIX 文件。 (在 windows 8.) 的文件资源管理器

    若要卸载该文件,请使用**“工具”菜单上的“扩展管理器”**。

编程验证

若要定义层验证扩展,请定义一个具有以下特征的类:

  • 声明的总体形式如下所示:

    
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
    using Microsoft.VisualStudio.GraphModel;
    ...
     [Export(typeof(IValidateArchitectureExtension))]
      public partial class Validator1Extension :
                      IValidateArchitectureExtension
      {
        public void ValidateArchitecture(Graph graph)
        {
           GraphSchema schema = graph.DocumentSchema;
          ...
      } }
    
  • 当您发现错误时,可使用 LogValidationError() 报告错误。

    警告

    不要使用 LogValidationError可选参数。

当用户调用**“验证体系结构”**菜单命令时,层运行时系统对层及其项目进行分析来生成关系图。 此关系图包括四部分:

  • Visual Studio 解决方案的层模型,表示为关系图中的节点和链接。

  • 解决方案中定义的代码、项目项和其他项目,表示为表示分析过程发现的依赖项的节点和链接。

  • 从层节点到代码项目节点的链接。

  • 表示验证程序发现的错误的节点。

关系图构造完成后,调用标准验证方法。 此过程完成后,将按未指定的顺序调用任意已安装的扩展验证方法。 将关系图传递给每个 ValidateArchitecture 方法,然后该方法可以扫描关系图并报告它发现的任何错误。

备注

这与应用到 UML 关系图的验证过程不相同,而且与可通过域特定语言使用的验证过程也不相同。

验证方法不应更改正在验证的层模型或代码。

关系图模型在 Microsoft.VisualStudio.GraphModel 中定义, 其主体类为 GraphNodeGraphLink

每个节点和每个链接都有一个或多个类别,用来指定它表示的元素或关系的类型。 典型关系图的节点具有以下类别:

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

代码中从层到元素的链接具有“Represents”类别。

调试验证

若要调试层验证扩展,请按 Ctrl+F5。 Visual Studio 的实验实例将打开。 在此实例中打开或创建一个层模型。 此模型必须与代码关联,且必须具有至少一个依赖项。

Ff657807.collapse_all(zh-cn,VS.110).gif测试包含依赖项的解决方案

除非具有以下特征,否则不执行验证:

  • 在层关系图上存在至少一个依赖项链接。

  • 模型中存在一些与代码元素关联的层。

首次启动 Visual Studio 的实验实例来测试您的验证扩展时,打开或创建一个具有这些特征的解决方案。

Ff657807.collapse_all(zh-cn,VS.110).gif运行“验证体系结构”命令之前运行“清理解决方案”命令

每当更新验证代码时,请首先在实验解决方案中使用**“生成”菜单上的“清理解决方案”**命令,然后再测试“验证”命令。 这是必需的,原因是验证结果会被缓存。 如果您尚未更新测试层关系图或其代码,则将不会执行验证方法。

Ff657807.collapse_all(zh-cn,VS.110).gif显式启动调试器

验证将在单独的进程中运行。 因此,在您的验证方法中的断点不会触发。 验证启动后,必须显式地将调试器附加到进程。

若要将调试器附加到验证进程,请在验证方法的开头插入对 System.Diagnostics.Debugger.Launch() 的调用。 当调试对话框出现时,选择 Visual Studio 的主实例。

或者,也可以插入对 System.Windows.Forms.MessageBox.Show() 的调用。 当出现消息框时,转到 Visual Studio 主实例中 调试 菜单中单击 附加到进程。选择名为 Graphcmd.exe的过程。

始终通过按 Ctrl+F5(“开始执行(不调试)”)来启动此实验实例。

Ff657807.collapse_all(zh-cn,VS.110).gif部署验证扩展

若要在安装了 Visual Studio 旗舰版或 Visual Studio 高级专业版的计算机上安装您的验证扩展,请在目标计算机上打开 VSIX 文件。 若要在安装了 Team Foundation Build 的计算机上进行安装,必须将 VSIX 内容手动提取到 Extensions 文件夹中。 有关更多信息,请参见部署层建模扩展

代码示例

using System;
using System.ComponentModel.Composition;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.GraphModel;

namespace Validator3
{
    [Export(typeof(IValidateArchitectureExtension))]
    public partial class Validator3Extension : IValidateArchitectureExtension
    {
        /// <summary>
        /// Validate the architecture
        /// </summary>
        /// <param name="graph">The graph</param>
        public void ValidateArchitecture(Graph graph)
        {
            if (graph == null) throw new ArgumentNullException("graph");

            // Uncomment the line below to debug this extension during validation
            // System.Windows.Forms.MessageBox.Show("Attach 2 to GraphCmd.exe with process id " + System.Diagnostics.Process.GetCurrentProcess().Id);


            // Get all layers on the diagram
            foreach (GraphNode layer in graph.Nodes.GetByCategory("Dsl.Layer"))
            {
                System.Threading.Thread.Sleep(100);
                // Get the required regex property from the layer node
                string regexPattern = "^[a-zA-Z]+$"; //layer[customPropertyCategory] as string;
                if (!string.IsNullOrEmpty(regexPattern))
                {
                    Regex regEx = new Regex(regexPattern);

                    // Get all referenced types in this layer including those from nested layers so each
                    // type is validated against all containing layer constraints.
                    foreach (GraphNode containedType in layer.FindDescendants().Where(node => node.HasCategory("CodeSchema_Type")))
                    {
                        // Check the type name against the required regex                        
                        CodeGraphNodeIdBuilder builder = new CodeGraphNodeIdBuilder(containedType.Id, graph);
                        string typeName = builder.Type.Name;
                        if (!regEx.IsMatch(typeName))
                        {
                            // Log an error
                            string message = string.Format(CultureInfo.CurrentCulture, Resources.InvalidTypeNameMessage, typeName);
                            this.LogValidationError(graph, typeName + "TypeNameError", message, GraphErrorLevel.Error, layer);
                        }
                    }
                }

            }

        }
    }
}

请参见

概念

扩展层关系图