Share via


使用 DTDL 剖析器程式庫剖析並驗證模型

本文說明如何使用 .NET 剖析器程式庫剖析及驗證 Azure Digital Twins 模型。

Azure Digital Twins 模型是使用 JSON-LD 型數位對應項定義語言 (DTDL) 來定義。

建立模型之後,建議您先離線驗證模型,再將模型上傳至 Azure Digital Twins 執行個體。

為了協助您驗證模型,NuGet 上會提供 .NET 用戶端 DTDL 剖析連結庫:DTDLParser。 您可以直接在 C# 程式碼中使用剖析器程式庫。 您也可以在 GitHub 中檢視DTDLParserResolveSample 中的剖析器範例使用方式。

關於 .NET 剖析器程式庫

DTDLParser 程式庫提供 DTDL 定義的模型存取權,基本上作為等同於 DTDL 的 C# 反映。 此程式庫可以獨立於任何 Azure Digital Twins SDK 來使用,特別是用於視覺編輯器或文字編輯器中的 DTDL 驗證。 在嘗試將模型定義檔案上傳至服務之前,請務必確定模型定義檔案有效。

若要使用剖析器程式庫,請提供一組 DTDL 文件。 一般而言會從服務擷取這些模型文件,但如果客戶一開始就負責將其上傳至服務,則您亦可能是在本機取得這些模型文件。

以下為使用剖析器的一般工作流程:

  1. 從服務擷取部分或所有 DTDL 文件。
  2. 將傳回的記憶體內 DTDL 文件傳遞至剖析器。
  3. 剖析器會驗證傳遞給它的一組文件,並傳回詳細的錯誤資訊。 這項功能在編輯器案例中會很有用。
  4. 使用剖析器 API 以繼續分析文件集合所包含的模型。

剖析器的功能包括:

  • 取得所有實作的模型介面 (介面內容的 extends 區段)。
  • 取得模型中宣告的所有屬性、遙測、命令、元件和關聯性。 此命令亦會取得在這些定義中包含的所有中繼資料,並將繼承 (extends 區段) 計入。
  • 取得所有複雜的模型定義。
  • 判斷這一個模型是否可從另一個模型指派。

注意

IoT 隨插即用裝置會使用小型語法變體來描述其功能。 此語法變體是在 Azure Digital Twins 中使用語意相容子集的 DTDL。 使用剖析器程式庫時,不需要知道是使用哪一種語法變體來建立適用於數位對應項的 DTDL。 根據預設,剖析器會針對 IoT 隨插即用和 Azure Digital Twins 語法傳回相同模型。

使用剖析器程式庫撰寫程式碼

您可以直接使用剖析器程式庫,例如在您自己的應用程式中驗證模型,或產生由模型提供的動態 UI、儀表板和報告。

若要支援下列剖析器程式碼範例,可考慮使用在 Azure Digital Twins 執行個體中定義的數種模型:

[
    {
      "@context": "dtmi:dtdl:context;3",
      "@id": "dtmi:com:contoso:coffeeMaker;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": "Component",
          "name": "coffeeMaker",
          "schema": "dtmi:com:contoso:coffeeMakerInterface;1"
        }
      ]
    },
    {
      "@context": "dtmi:dtdl:context;3",
      "@id": "dtmi:com:contoso:coffeeMakerInterface;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": "Property",
          "name": "waterTemp",
          "schema": "double"
        }
      ]
    },
    {
      "@context": "dtmi:dtdl:context;3",
      "@id": "dtmi:com:contoso:coffeeBar;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": "Relationship",
          "name": "foo",
          "target": "dtmi:com:contoso:coffeeMaker;1"
        },
        {
          "@type": "Property",
          "name": "capacity",
          "schema": "integer"
        }
      ]
    }
  ]

下列程式碼示範如何使用剖析器程式庫反映在 C# 中這些所定義的範例:

using Azure;
using Azure.DigitalTwins.Core;
using DTDLParser;
using DTDLParser.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DigitalTwins_Samples
{
    public static class ListExtensions
    {
        public static async IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IEnumerable<T> input)
        {
            foreach (var value in input)
            {
                yield return value;
            }
            await Task.Yield();
        }
    }

    public class ParseModelsSample
    {
        public async Task ParseDemoAsync(DigitalTwinsClient client)
        {
            try
            {
                AsyncPageable<DigitalTwinsModelData> mdata = client.GetModelsAsync(new GetModelsOptions { IncludeModelDefinition = true });
                var models = new List<string>();
                await foreach (DigitalTwinsModelData md in mdata)
                    models.Add(md.DtdlModel);
                var parser = new ModelParser();
                IReadOnlyDictionary<Dtmi, DTEntityInfo> dtdlOM = await parser.ParseAsync(models.AsAsyncEnumerable());

                var interfaces = new List<DTInterfaceInfo>();
                IEnumerable<DTInterfaceInfo> ifenum =
                    from entity in dtdlOM.Values
                    where entity.EntityKind == DTEntityKind.Interface
                    select entity as DTInterfaceInfo;
                interfaces.AddRange(ifenum);
                foreach (DTInterfaceInfo dtif in interfaces)
                {
                    PrintInterfaceContent(dtif, dtdlOM);
                }
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"Failed due to {ex}");
                throw;
            }
        }

        public void PrintInterfaceContent(DTInterfaceInfo dtif, IReadOnlyDictionary<Dtmi, DTEntityInfo> dtdlOM, int indent = 0)
        {
            var sb = new StringBuilder();
            for (int i = 0; i < indent; i++) sb.Append("  ");
            Console.WriteLine($"{sb}Interface: {dtif.Id} | {dtif.DisplayName}");
            IReadOnlyDictionary<string, DTContentInfo> contents = dtif.Contents;

            foreach (DTContentInfo item in contents.Values)
            {
                switch (item.EntityKind)
                {
                    case DTEntityKind.Property:
                        DTPropertyInfo pi = item as DTPropertyInfo;
                        Console.WriteLine($"{sb}--Property: {pi.Name} with schema {pi.Schema}");
                        break;
                    case DTEntityKind.Relationship:
                        DTRelationshipInfo ri = item as DTRelationshipInfo;
                        Console.WriteLine($"{sb}--Relationship: {ri.Name} with target {ri.Target}");
                        break;
                    case DTEntityKind.Telemetry:
                        DTTelemetryInfo ti = item as DTTelemetryInfo;
                        Console.WriteLine($"{sb}--Telemetry: {ti.Name} with schema {ti.Schema}");
                        break;
                    case DTEntityKind.Component:
                        DTComponentInfo ci = item as DTComponentInfo;
                        Console.WriteLine($"{sb}--Component: {ci.Id} | {ci.Name}");
                        DTInterfaceInfo component = ci.Schema;
                        PrintInterfaceContent(component, dtdlOM, indent + 1);
                        break;                
                }
            }
        }
    }
}

下一步

撰寫模型之後,請參閱如何使用 Azure Digital Twins 模型 API 將其上傳 (並執行其他管理作業):