Skip to content

Commit e6fdf9f

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents 04e4457 + 529b251 commit e6fdf9f

342 files changed

Lines changed: 4383 additions & 2105 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-and-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ on:
1414
- future
1515

1616
env:
17-
dotnet_sdk_version: "10.0.100"
17+
dotnet_sdk_version: "10.0.400"
1818
node_version: "24"
1919
REPOSITORY_NAME: ${{ github.event.repository.name }}
2020
MORYX_PACKAGE_TARGET_DEV: "https://www.myget.org/F/moryx-oss-ci/api/v2/package"

Directory.Packages.props

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
</PropertyGroup>
99

1010
<PropertyGroup>
11-
<dotnetVersion>10.0.0</dotnetVersion>
11+
<dotnetVersion>10.0.11</dotnetVersion>
1212
</PropertyGroup>
1313

1414
<ItemGroup>
1515
<!-- Test libraries -->
16-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
16+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.0" />
1717
<PackageVersion Include="Moq" Version="4.20.72" />
18-
<PackageVersion Include="NUnit" Version="4.4.0" />
19-
<PackageVersion Include="NUnit3TestAdapter" Version="5.2.0" />
20-
<PackageVersion Include="NUnit.Analyzers" Version="4.11.2" />
21-
<PackageVersion Include="WireMock.Net" Version="1.16.0" />
22-
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
18+
<PackageVersion Include="NUnit" Version="4.6.1" />
19+
<PackageVersion Include="NUnit3TestAdapter" Version="6.2.0" />
20+
<PackageVersion Include="NUnit.Analyzers" Version="4.14.0" />
21+
<PackageVersion Include="WireMock.Net" Version="2.14.0" />
22+
<PackageVersion Include="coverlet.collector" Version="10.0.1" />
2323

2424
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(dotnetVersion)" />
2525
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(dotnetVersion)" />
@@ -47,10 +47,10 @@
4747
<PackageVersion Include="Microsoft.Identity.Web" Version="4.0.0" />
4848
<PackageVersion Include="Microsoft.Identity.Web.DownstreamApi" Version="4.0.0" />
4949

50-
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
50+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.400" />
5151

5252
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
53-
<PackageVersion Include="Swashbuckle.AspNetCore" Version="8.1.4" />
53+
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.2.3" />
5454

5555
<PackageVersion Include="Castle.Windsor" Version="6.0.0" />
5656

MORYX-Framework.slnx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120
<Project Path="src/Tests/Moryx.Shifts.Management.IntegrationTests/Moryx.Shifts.Management.IntegrationTests.csproj" />
121121
</Folder>
122122
<Folder Name="/Tests/UnitTests/">
123-
<Project Path="src/Tests/Moryx.AspNetCore.Mqtt.Tests/Moryx.AspNetCore.Mqtt.Tests.csproj" />
124123
<Project Path="src/Tests/Moryx.AbstractionLayer.Tests/Moryx.AbstractionLayer.Tests.csproj" />
124+
<Project Path="src/Tests/Moryx.AspNetCore.Mqtt.Tests/Moryx.AspNetCore.Mqtt.Tests.csproj" />
125125
<Project Path="src/Tests/Moryx.Container.Tests/Moryx.Container.Tests.csproj" />
126126
<Project Path="src/Tests/Moryx.ControlSystem.ProcessEngine.Tests/Moryx.ControlSystem.ProcessEngine.Tests.csproj" />
127127
<Project Path="src/Tests/Moryx.ControlSystem.SetupProvider.Tests/Moryx.ControlSystem.SetupProvider.Tests.csproj" />
@@ -146,10 +146,11 @@
146146
<Project Path="src/Tests/Moryx.Runtime.Tests/Moryx.Runtime.Tests.csproj" />
147147
<Project Path="src/Tests/Moryx.Simulation.Tests/Moryx.Simulation.Tests.csproj" />
148148
<Project Path="src/Tests/Moryx.Tests/Moryx.Tests.csproj" />
149-
<Project Path="src/Tests/Moryx.VisualInstructions.Tests/Moryx.VisualInstructions.Tests.csproj" />
150-
<Project Path="src/Tests/Moryx.Workplans.Editing.Tests/Moryx.Workplans.Editing.Tests.csproj" />
151149
<Project Path="src/Tests/Moryx.VisualInstructions.Controller.Tests/Moryx.VisualInstructions.Controller.Tests.csproj" />
152150
<Project Path="src/Tests/Moryx.VisualInstructions.Endpoints.Tests/Moryx.VisualInstructions.Endpoints.Tests.csproj" />
151+
<Project Path="src/Tests/Moryx.AbstractionLayer.Resources.Endpoints.Tests/Moryx.AbstractionLayer.Resources.Endpoints.Tests.csproj" />
152+
<Project Path="src/Tests/Moryx.VisualInstructions.Tests/Moryx.VisualInstructions.Tests.csproj" />
153+
<Project Path="src/Tests/Moryx.Workplans.Editing.Tests/Moryx.Workplans.Editing.Tests.csproj" />
153154
</Folder>
154155
<Folder Name="/TestTools/">
155156
<Project Path="src/Moryx.AbstractionLayer.TestTools/Moryx.AbstractionLayer.TestTools.csproj" />
@@ -165,11 +166,11 @@
165166
<Project Path="src/Tests/Moryx.Container.TestTools/Moryx.Container.TestTools.csproj" />
166167
</Folder>
167168
<Folder Name="/VisualInstructions/">
168-
<Project Path="src/Moryx.VisualInstructions/Moryx.VisualInstructions.csproj" />
169169
<Project Path="src/Moryx.Resources.VisualInstructions/Moryx.Resources.VisualInstructions.csproj" />
170170
<Project Path="src/Moryx.VisualInstructions.Controller/Moryx.VisualInstructions.Controller.csproj" />
171171
<Project Path="src/Moryx.VisualInstructions.Endpoints/Moryx.VisualInstructions.Endpoints.csproj" />
172172
<Project Path="src/Moryx.VisualInstructions.Web/Moryx.VisualInstructions.Web.csproj" />
173+
<Project Path="src/Moryx.VisualInstructions/Moryx.VisualInstructions.csproj" />
173174
</Folder>
174175
<Folder Name="/Workplans/">
175176
<Project Path="src/Moryx.Workplans.Editing/Moryx.Workplans.Editing.csproj" />

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
10.9.1
1+
10.9.2

docs/articles/framework/Serialization/entry-convert.md

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,41 @@ Because the `EntryConvert`-API can be confusing on first sight, we will split it
1111
* **Deserialize:** The encoded entry tree can be converted into objects after modification by the client with the overloads of `CreateInstance` and `UpdateInstance`
1212
* **Customization:** The behavior of both encoding and decoding can be customized to specific needs by providing a strategy implementing `ICustomSerialization`
1313

14+
## Supported Types
15+
16+
| .NET Type | EntryValueType | Format | Limitations |
17+
|-----------|---------------|--------|-------------|
18+
| `byte` | Byte |||
19+
| `bool` | Boolean |||
20+
| `short`, `ushort` | Int16, UInt16 |||
21+
| `int`, `uint` | Int32, UInt32 |||
22+
| `long`, `ulong` | Int64, UInt64 |||
23+
| `float` | Single | Culture-aware with invariant fallback ||
24+
| `double` | Double | Culture-aware with invariant fallback ||
25+
| `decimal` | Double | Culture-aware with invariant fallback | Mapped to `Double; may lose precision beyond ~15 significant digits |
26+
| `string` | String |||
27+
| `enum` | Enum | String name ||
28+
| `DateTime` | DateTime | ISO 8601 round-trip (`"O"`) | Converted to UTC; original `DateTimeKind` is lost |
29+
| `DateTimeOffset` | DateTime | ISO 8601 round-trip (`"O"`) | Converted to UTC; original timezone offset is lost |
30+
| `DateOnly` | Date | ISO 8601 round-trip (`"O"`) ||
31+
| `TimeOnly` | Time | ISO 8601 round-trip (`"O"`) ||
32+
| `TimeSpan` | TimeSpan | Constant format (`"c"`) ||
33+
| `Stream` | Stream | Base64 encoded | Limited by available memory |
34+
| `Vector2`, `Vector3`, `Vector4` | Struct | Decomposed into sub-entries (X, Y, Z, W) ||
35+
| `Quaternion` | Struct | Decomposed into sub-entries (X, Y, Z, W) ||
36+
| `Plane` | Struct | Decomposed into sub-entries (X, Y, Z, D) ||
37+
| Classes | Class | Recursive sub-entries | Requires public parameter-less constructor |
38+
| Collections | Collection | Recursive sub-entries ||
39+
| Dictionaries | Collection | Recursive sub-entries | Key must be a type supported by `ToObject` |
40+
1441
## Limitations
1542

1643
The `EntryConvert` API can convert objects and types as long as they comply with a few basic rules:
1744

1845
* Properties not fields: All attributes of a type must be defined as properties, not public fields. Therefor `public int Foo { get; set; }` instead of `public int Foo;`
19-
* Public parameter-less constructor: All types within the class hierarchy need to offer a public constructor without parameters. In Generics this would be defined as `new()` or in code `public Foo() { }`. For the root object `EntryConvert` can extract Constructors as `MethodEntry`, which can be exchanged with a client and used to create instances.
20-
* Primitives or classes: The reflection approach used to deserialize the entry tree to objects requires reference access. Otherwise the modifications will only take part on a copy. Therefor properties need to be either of a primitive type like int, string, enum or a another class.
21-
* Dictionaries of `<Primitive, Class`: Dictionaries are only supported if the key is a primitive type like `int` or `string` and the value is a class.
46+
* Public parameter-less constructor: All types within the class hierarchy need to offer a public constructor without parameters. In Generics this would be defined as `new()` or in code `public Foo() { }`. For the root object `EntryConvert` can extract Constructors as `MethodEntry`, which can be exchanged with a client and used to create instances.
47+
* Primitives, classes or supported structs: The reflection approach used to deserialize the entry tree to objects requires reference access. Otherwise the modifications will only take part on a copy. Therefor properties need to be either of a primitive type like int, string, enum, a class, or a supported struct (`Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Plane`). Supported structs are automatically decomposed into editable sub-entries.
48+
* Dictionary keys: Dictionary keys must be a type supported by `ToObject`, i.e. any type that can be converted to and from a string representation.
2249

2350
## Serialize Objects
2451

@@ -141,6 +168,37 @@ public void Deserialize(Entry entry, FileStreamDummy dummy)
141168
}
142169
````
143170

171+
## Serialize Structs
172+
173+
`EntryConvert` supports decomposed serialization for the following `System.Numerics` struct types: `Vector2`, `Vector3`, `Vector4`, `Quaternion` and `Plane`. Instead of displaying unparseable strings like `<1.5, 2.5, 3.5>`, these structs are encoded as `Struct` entries with editable sub-entries for each component (X, Y, Z, W). When you serialize a class containing one of these types, the resulting entry will have sub-entries for each component of the struct.
174+
175+
````cs
176+
public class RobotPosition
177+
{
178+
public Vector3 Position { get; set; }
179+
public Quaternion Orientation { get; set; }
180+
}
181+
182+
public void Serialize()
183+
{
184+
var pos = new RobotPosition
185+
{
186+
Position = new Vector3(1.5f, 2.5f, 3.5f),
187+
Orientation = new Quaternion(0, 0, 0, 1)
188+
};
189+
var entry = EntryConvert.EncodeObject(pos);
190+
// entry.SubEntries[0] (Position) has SubEntries: X=1.5, Y=2.5, Z=3.5
191+
// entry.SubEntries[1] (Orientation) has SubEntries: X=0, Y=0, Z=0, W=1
192+
}
193+
194+
public void Deserialize(Entry entry)
195+
{
196+
var pos = new RobotPosition();
197+
EntryConvert.UpdateInstance(pos, entry);
198+
// pos.Position and pos.Orientation are reconstructed from sub-entry values
199+
}
200+
````
201+
144202
## ICustomSerialization
145203

146204
All public methods of `EntryConvert` have overloads that expect an instance of [ICustomSerialization](/src/Moryx/Serialization/ICustomSerialization.cs) to modify the behavior of the serializer where necessary. The overloads without the parameter use a Singleton instance of `DefaultSerialization`. When implementing a new version of `ICustomSerialization` it is recommended to derive from [DefaultSerialization](/src/Moryx/Serialization/DefaultSerialization.cs) and only override what shall behave different.
@@ -232,4 +290,4 @@ public Entry InvokeMethod(MethodEntry method)
232290

233291
### Serialize Constructors
234292

235-
In the previous sections, it was described that `EntryConvert` can also serialize constructors. The [EntrySerializeSerialization](/src/Moryx/Serialization/EntrySerializeSerialization.cs) only serializes constructors like methods with the [EntrySerializeAttribute](/src/Moryx/Serialization/EntryConvert/EntrySerializeAttribute.cs) defined.
293+
In the previous sections, it was described that `EntryConvert` can also serialize constructors. The [EntrySerializeSerialization](/src/Moryx/Serialization/EntrySerializeSerialization.cs) only serializes constructors like methods with the [EntrySerializeAttribute](/src/Moryx/Serialization/EntryConvert/EntrySerializeAttribute.cs) defined.

docs/articles/module-products/generic-strategies.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,34 @@ Property mappers are strategies to map a single property to a database column an
1111

1212
| Name | Column Type | Supported Property Types |
1313
|---|---|---|
14-
| [IntegerColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/IntegerColumnMapper.cs) | long | Int16 - UInt64 , Enum, DateTime, bool |
15-
| [FloatColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/FloatColumnMapper.cs) | double | Float, Double, Decimal |
16-
| [TextColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/TextColumnMapper.cs) | string | string (plain), object (JSON) |
14+
| [IntegerColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/IntegerColumnMapper.cs) | long | Int16 - UInt64, Enum, DateTime, DateOnly, TimeOnly, bool |
15+
| [FloatColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/FloatColumnMapper.cs) | double | float, double, decimal |
16+
| [TextColumnMapper](/src/Moryx.Products.Management/Plugins/GenericStrategies/TextColumnMapper.cs) | string | string (plain), Guid, classes/interfaces (JSON), non-primitive structs like Vector2, Vector3, Vector4, Quaternion, Plane, DateTimeOffset (JSON) |
17+
18+
### IntegerColumnMapper
19+
20+
The `IntegerColumnMapper` stores values as `long` in the database.
21+
22+
- Int16 - UInt64 are stored directly
23+
- Enums are converted to their underlying integer type
24+
- `DateTime` is stored as `Ticks`
25+
- `DateOnly` is stored as `DayNumber` (days since 0001-01-01)
26+
- `TimeOnly` is stored as `Ticks` (ticks since midnight)
27+
- `bool` is stored as `1` or `0`
28+
29+
### FloatColumnMapper
30+
31+
The `FloatColumnMapper` stores values as `double` in the database. Supports `float`, `double` and `decimal` properties.
32+
33+
> **Note:** IEEE 754 special values (`NaN`, `+Infinity`, `-Infinity`) are not supported by all databases. PostgreSQL stores them natively in `float8`, but SQLite throws on `REAL` columns. The `SqliteProductsContext` registers an [Ieee754ValueConverter](/src/Moryx.Products.Management/Model/Ieee754ValueConverter.cs) that encodes these as sentinel values before writing and decodes them back when reading.
34+
35+
### TextColumnMapper
36+
37+
The `TextColumnMapper` stores values as `string` in the database.
38+
39+
- `string` is stored directly
40+
- `Guid` is converted to its string representation
41+
- Classes, interfaces and non-primitive structs (e.g. `Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Plane`, `DateTimeOffset`) are serialized as JSON
1742

1843
## Configuration
1944

0 commit comments

Comments
 (0)