diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/AttributeValueCodec.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/AttributeValueCodec.cs index c4abd822..ecc4cbea 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/AttributeValueCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/AttributeValueCodec.cs @@ -72,6 +72,8 @@ public static class AttributeValueCodec private static object? ParseScalar(string? s, DataType t) { if (s is null) throw new FormatException("List elements may not be null."); + if (!IsValidElementType(t)) + throw new FormatException($"Unsupported list element type '{t}'."); var c = CultureInfo.InvariantCulture; try { diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs index 72dd1eaa..8456c69e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs @@ -524,6 +524,7 @@ public class ManagementActor : ReceiveActor CanonicalName = a.Name, Value = a.Value, DataType = a.DataType.ToString(), + ElementDataType = a.ElementDataType?.ToString(), IsLocked = a.IsLocked, DataSourceReference = a.DataSourceReference }).ToList(), diff --git a/src/ZB.MOM.WW.ScadaBridge.Transport/Import/BundleImporter.cs b/src/ZB.MOM.WW.ScadaBridge.Transport/Import/BundleImporter.cs index 5b9f968e..a93d34bc 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Transport/Import/BundleImporter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Transport/Import/BundleImporter.cs @@ -1083,8 +1083,8 @@ public sealed class BundleImporter : IBundleImporter /// enumerates for the "Template overwritten" action. /// /// Update detection compares every scalar field (Value, DataType, - /// IsLocked, Description, DataSourceReference) — no field change → no - /// audit row, so an idempotent overwrite produces no noise. + /// ElementDataType, IsLocked, Description, DataSourceReference) — no field + /// change → no audit row, so an idempotent overwrite produces no noise. /// /// private async Task SyncTemplateAttributesAsync( @@ -1146,6 +1146,7 @@ public sealed class BundleImporter : IBundleImporter AttributeName = current.Name, current.Value, current.DataType, + current.ElementDataType, current.IsLocked, current.Description, current.DataSourceReference, @@ -1176,6 +1177,7 @@ public sealed class BundleImporter : IBundleImporter AttributeName = newAttr.Name, newAttr.Value, newAttr.DataType, + newAttr.ElementDataType, newAttr.IsLocked, newAttr.Description, newAttr.DataSourceReference, @@ -2304,6 +2306,7 @@ public sealed class BundleImporter : IBundleImporter CanonicalName = a.Name, Value = a.Value, DataType = a.DataType.ToString(), + ElementDataType = a.ElementDataType?.ToString(), IsLocked = a.IsLocked, Description = a.Description, DataSourceReference = a.DataSourceReference, diff --git a/tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/Types/AttributeValueCodecTests.cs b/tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/Types/AttributeValueCodecTests.cs index ac4dce9e..a4aed551 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/Types/AttributeValueCodecTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/Types/AttributeValueCodecTests.cs @@ -49,6 +49,14 @@ public class AttributeValueCodecTests Assert.Equal("[\"ACME, Inc.\"]", AttributeValueCodec.Encode(new List { "ACME, Inc." })); + [Fact] + public void RoundTrip_FloatList() + { + var json = AttributeValueCodec.Encode(new List { 1.5f, 2.25f, -3.75f }); + var back = (IList)AttributeValueCodec.Decode(json, DataType.List, DataType.Float)!; + Assert.Equal(new[] { 1.5f, 2.25f, -3.75f }, back); + } + [Fact] public void Encode_DoubleList_IsInvariant() {