使用 DTDL 剖析器連結庫剖析和驗證模型
本文說明如何使用 .NET 剖析器連結庫剖析及驗證 Azure Digital Twins 模型。
Azure Digital Twins 中的模型 是使用 JSON-LD 型數字對應項定義語言 (DTDL) 來定義。
建立模型之後,建議您先脫機驗證模型,再將其上傳至 Azure Digital Twins 實例。
為了協助您驗證模型,NuGet: DTDLParser 上會提供 .NET 用戶端 DTDL 剖析連結庫。 您可以直接在 C# 程式代碼中使用剖析器連結庫。 您也可以檢視 GitHub 中 DTDLParserResolveSample 中剖析器範例的使用。
關於 .NET 剖析器連結庫
DTDLParser 連結庫提供 DTDL 定義的模型存取權,基本上相當於 DTDL 的 C# 反映。 此連結庫可以獨立於任何 Azure Digital Twins SDK 使用,特別是在視覺效果或文本編輯器中用於 DTDL 驗證。 在嘗試將模型定義檔案上傳至服務之前,請務必確定模型定義檔案有效。
若要使用剖析器連結庫,請提供一組 DTDL 檔。 一般而言,您會從服務擷取這些模型檔,但如果客戶端負責先將其上傳至服務,您可能也會在本機取得這些模型檔。
以下是使用剖析器的一般工作流程:
- 從服務擷取部分或所有 DTDL 檔。
- 將傳回的記憶體內部 DTDL 檔案傳遞至剖析器。
- 剖析器會驗證傳遞給它的檔集,並傳回詳細的錯誤資訊。 這項功能在編輯器案例中很有用。
- 使用剖析器 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 上傳它們(並執行其他管理作業):