forked from ZeraGmbH/Blockly.Net
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ReadFromModel.cs
109 lines (99 loc) · 3.23 KB
/
ReadFromModel.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using System.Collections;
using System.Reflection;
using BlocklyNet.Core.Blocks;
using BlocklyNet.Core.Blocks.Lists;
using BlocklyNet.Core.Model;
using BlocklyNet.Extensions.Builder;
namespace BlocklyNet.Extensions;
/// <summary>
/// Read a single property from a model.
/// </summary>
[CustomBlock(
"read_model_property",
"",
@"{
""message0"": ""ReadFromModel %1 %2 %3 %4 %5 %6"",
""args0"": [
{
""type"": ""field_variable"",
""name"": ""VAR"",
""text"": ""Variable""
},
{
""type"": ""input_dummy""
},
{
""type"": ""field_label_serializable"",
""name"": ""PATH"",
""text"": ""Path to value""
},
{
""type"": ""input_value"",
""name"": ""PATH"",
""check"": ""String""
},
{
""type"": ""field_label_serializable"",
""name"": ""INDEXES"",
""text"": ""Indexes in path""
},
{
""type"": ""input_value"",
""name"": ""INDEXES"",
""check"": [""Array(Number)"", ""Array""]
}
],
""output"": null,
""colour"": ""#107159"",
""tooltip"": ""Read a single field from a model variable"",
""helpUrl"": """"
}",
@"{
""inputs"": {
""PATH"": {
""shadow"": {
""type"": ""text"",
""fields"": {
""TEXT"": """"
}
}
}
}
}"
)]
public class ReadFromModel : Block
{
/// <inheritdoc/>
public override async Task<object?> EvaluateAsync(Context context)
{
var varName = Fields["VAR"];
var data = context.Variables.TryGetValue(varName, out var local) ? local : context.GetRootContext().Variables[varName];
var path = await Values.EvaluateAsync<string>("PATH", context) ?? "";
var rawIndexes = await Values.EvaluateAsync<IEnumerable>("INDEXES", context, false);
var indexes = rawIndexes?.Cast<object>().ToArray() ?? [];
var parts = path.Split(".");
var i = 0;
foreach (var part in parts)
{
var isArray = part.EndsWith("[]");
var field = isArray ? part[..^2] : part;
/* Read from a string dictionary - e.g. some ExpandoObject. */
if (data is IDictionary<string, object> stringSource)
data = stringSource[field];
/* Read from generic dictionary. */
else if (data is IDictionary source)
{
/* Check key type. */
var keyType = source.GetType().GetGenericArguments()[0];
data = source[keyType.IsEnum ? Enum.Parse(keyType, field) : field];
}
/* Read from .NET instance. */
else
data = data!.GetType().InvokeMember(field, BindingFlags.GetProperty | BindingFlags.GetField, null, data, null)!;
/* Resolve index. */
if (isArray)
data = new ListWrapper(data)[Convert.ToInt32(indexes[i++]) - 1];
}
return data;
}
}