You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The identity system in AXSharp allows twin objects to be looked up by a unique numeric identity (`ulong`). This is used by components that need to resolve references between twin objects at runtime (e.g. the `[MemberByIdentity]` attribute).
6
+
7
+
The core class is [`TwinIdentityProvider`](~/api/AXSharp.Connector.Identity.TwinIdentityProvider.yml), which is responsible for assigning, writing, and sorting identity values.
8
+
9
+
## How identities work
10
+
11
+
1. During twin construction, each object that implements `ITwinIdentity` is registered via `AddIdentity`.
12
+
2. When the application starts, `ConstructIdentitiesAsync` is called to assign identity values, write them to the PLC, and build a sorted lookup dictionary.
13
+
3. Other parts of the system can then resolve objects by their identity using `GetTwinByIdentity`.
`ConstructIdentitiesAsync` performs the following steps:
22
+
23
+
1.**Assign** -- Each identity tag is assigned a `ulong` value using the provided `identityProvider` function. If no function is supplied, a default provider based on `string.GetHashCode()` of the symbol is used.
24
+
2.**Write** -- The assigned values are written to the PLC via `WriteBatchAsync`. Values are always written fresh, regardless of what was previously stored on the PLC.
25
+
3.**Sort** -- The identities are sorted into a `SortedDictionary<ulong, ITwinIdentity>` using the locally assigned values (`Cyclic`), not values read back from the PLC.
26
+
27
+
This ensures that stale or inconsistent identity values left on the PLC from prior sessions cannot cause errors.
By default, `ConstructIdentitiesAsync` throws a `DuplicateIdentityException` when two symbols resolve to the same identity value. You can set `failOnDuplicate` to `false` to log a warning and skip the duplicate entry instead.
36
+
37
+
## Custom identity providers
38
+
39
+
The default identity provider uses `string.GetHashCode()`, which has two important limitations:
40
+
41
+
-**Not deterministic across processes** -- In .NET Core/.NET 5+, `string.GetHashCode()` is randomized per process. Identity values will differ between application restarts.
42
+
-**Collision risk** -- `GetHashCode()` returns a 32-bit value. For large PLC programs with many symbols, hash collisions become increasingly likely (birthday paradox).
43
+
44
+
For production use, supply a custom identity provider that guarantees uniqueness:
- Produce deterministic values for the same symbol across process restarts.
54
+
- Guarantee uniqueness (or near-uniqueness) across all symbols in the program.
55
+
- Use the full 64-bit `ulong` range to minimize collision probability.
56
+
57
+
## Troubleshooting
58
+
59
+
### `DuplicateIdentityException`
60
+
61
+
This exception is thrown when two different symbols are assigned the same identity value. Common causes:
62
+
63
+
-**Hash collision** with the default `GetHashCode()`-based provider. Solution: use a custom identity provider with better distribution, or set `failOnDuplicate: false` if identity-based lookups are not critical for your application.
64
+
-**Stale PLC values** (resolved in current version) -- Previously, the identity system would read back values from the PLC after writing. If the PLC returned stale data from a prior session, this could cause spurious duplicate errors. The system now uses the locally assigned values directly, avoiding this issue.
Copy file name to clipboardExpand all lines: src/AXSharp.connectors/tests/AXSharp.ConnectorTests/AXSharp.ConnectorTests/Identity/TwinIdentityProviderTests.cs
+3Lines changed: 3 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -220,16 +220,19 @@ public async void CanCallSortIdentities()
0 commit comments