This tutorial demonstrates basic interaction with this library's core class, ModelParser.
This class is used to determine whether one or more DTDL models are valid, to identify specific modeling errors, and to enable inspection of model contents.
This tutorial walks through the first of these uses: determining whether a model is valid.
A synchronous version of this tutorial is also available.
More detailed uses are covered in further tutorials.
To parse a DTDL model, you need to instantiate a ModelParser.
No arguments are required.
var modelParser = new ModelParser();The DTDL language is syntactically JSON.
The ModelParser expects a string value, which is JSON text of a DTDL model.
string jsonText1 =
@"{
""@context"": ""dtmi:dtdl:context;3"",
""@id"": ""dtmi:example:anInterface;1"",
""@type"": ""Interface"",
""contents"": [
{
""@type"": ""Telemetry"",
""name"": ""currentDistance"",
""schema"": ""double""
}
]
}";The main asynchronous method on the ModelParser is ParseAsync().
One argument is required: a string containing the JSON text to parse as DTDL.
var parseTask = modelParser.ParseAsync(jsonText1);The return value is a Task, whose completion must be awaited before proceeding.
If the submitted model is invalid or incomplete, an exception will be thrown, wrapped in an AggregateException by the System.Threading.Tasks framework.
If the submitted model is invalid, the wrapped exception will be a ParsingException.
If the submitted model is referentially incomplete, the wrapped exception will be a ResolutionException.
If no exception is thrown, the model is valid.
try
{
parseTask.Wait();
Console.WriteLine($"DTDL model is valid!");
}
catch (AggregateException ex)
{
if (ex.InnerException is ResolutionException)
{
Console.WriteLine($"DTDL model is referentially incomplete: {ex.InnerException}");
}
else if (ex.InnerException is ParsingException)
{
Console.WriteLine($"DTDL model is invalid: {ex.InnerException}");
}
else
{
throw;
}
}The JSON text above is valid DTDL, so the code snippet above will display:
DTDL model is valid!The JSON text of a DTDL model can contain a JSON array with multiple Interface definitions as elements of the array.
string jsonText2 =
@"{
""@context"": ""dtmi:dtdl:context;3"",
""@id"": ""dtmi:example:anotherInterface;1"",
""@type"": ""Interface"",
""contents"": [
{
""@type"": ""Property"",
""name"": ""expectedDistance"",
""schema"": ""double"",
""writable"": true
}
]
}";
string jsonText = $"[ {jsonText1}, {jsonText2} ]";parseTask = modelParser.ParseAsync(jsonText);The JSON text above, which contains two Interface definitions, is valid DTDL.
After waiting on the Task per the code snippet above, it displays:
DTDL model is valid!The ModelParser also expects an asynchronous enumeration of strings, each of which is JSON text of a DTDL model.
We can generate an asynchronous enumeration using a local function.
string[] jsonTexts = { jsonText1, jsonText2 };
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
async IAsyncEnumerable<string> GetJsonTexts(string[] jsonTexts)
{
foreach (string jsonText in jsonTexts)
{
yield return jsonText;
}
}
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronouslyThe asynchronous ParseAsync() method on the ModelParser, in addition to accepting a single string, also accepts an asynchronous enumeration of string values containing the JSON text to parse as DTDL.
parseTask = modelParser.ParseAsync(GetJsonTexts(jsonTexts));The enumeration of JSON texts above is valid DTDL.
After waiting on the Task per the code snippet above, it displays:
DTDL model is valid!