Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common/Classes.md
2026-04-17 14:55:32 -04:00

234 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common/Classes/UnityExtensions.cs
- Common/DTS.Common/Classes/StatusAndProgressBarEventArgs.cs
- Common/DTS.Common/Classes/Singleton.cs
- Common/DTS.Common/Classes/BulkObservableCollection.cs
- Common/DTS.Common/Classes/RegionNames.cs
- Common/DTS.Common/Classes/ImportData.cs
- Common/DTS.Common/Classes/ServiceCall.cs
- Common/DTS.Common/Classes/TagAwareBase.cs
- Common/DTS.Common/Classes/Utility.cs
- Common/DTS.Common/Classes/Tags.cs
generated_at: "2026-04-16T02:52:41.721329+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b71265395aaf09cd"
---
# DTS.Common Classes Documentation
## 1. Purpose
This module provides foundational infrastructure utilities for the DTS application platform, focusing on dependency injection (via Unity), UI state management (status/progress), singleton pattern enforcement, high-performance collection operations, service orchestration, database-backed tagging system, and robust data access helpers. It serves as a shared library across the application to standardize common patterns, reduce boilerplate, and ensure thread-safe, consistent behavior for core operations like service queuing, tag management, and database interaction.
## 2. Public Interface
### `UnityExtensions`
- **`T TryResolve<T>(this IUnityContainer container) where T : class`**
Safely resolves a service of type `T` from the Unity container, returning `null` instead of throwing on failure.
### `StatusAndProgressBarEventArgs`
- **Properties**
- `StatusColor`: `Color` UI color for status indication.
- `StatusText`: `string` Human-readable status message.
- `ProgressValue`: `double` Numeric progress (e.g., 0.01.0 or 0100).
- `ProgressBarVisibility`: `Visibility` Controls whether the progress bar is visible.
- `Requester`: `IBaseViewModel` Originator of the status update.
- `ErrorText`: `string` Optional error message to display.
### `Singleton<T>`
- **`protected Singleton()`**
Constructor enforces singleton usage: throws `InvalidOperationException` if called directly (i.e., via `new T()` instead of `T.Instance`).
- **`public static T Instance`**
Gets the singleton instance. Throws the exception captured during static initialization if instance creation failed.
### `BulkObservableCollection<T>`
- **`void AddRange(IEnumerable<T> items)`**
Adds multiple items to the collection and fires a single `NotifyCollectionChangedAction.Reset` notification instead of per-item notifications. Logs exceptions via `APILogger`.
- **`void RemoveRange(IEnumerable<T> itemsToRemove)`**
Removes multiple items and fires a single `Reset` notification. Logs exceptions via `APILogger`.
### `RegionNames`
- **Constants**
Static string constants defining Prism region names used for UI composition (e.g., `"FrontRegion"`, `"MainRegion"`, `"ViewerGraphMainRegion"`, `"MenuRegion"`). No methods.
### `ImportData`
- **`enum ImportPageType`**
- `ImportSensor`, `ImportTestSetup`
- **`class SensorImportData`**
Holds parsed sensor import data:
- `GroupNameSensorListLookup`: `Dictionary<string, List<string>>`
- `SensorGroupNameLookup`, `SensorGroupTypeLookup`, `GroupNameTestObjectLookup`: `Dictionary<string, string>`
- `Errors`: `List<string>`
- `SensorISOCode`, `SensorISOChannelName`, `SensorUserCode`, `SensorUserChannelName`, `SensorDASSerialNumber`: `Dictionary<string, string>`
- `SensorChannelIndex`: `Dictionary<string, int>`
- **`class TestSetupImportData`**
Holds parsed test setup import data:
- `Name`, `Description`: `string`
- `SamplesPerSecond`, `PosttriggerSeconds`, `PretriggerSeconds`: `double`
- `RecordingMode`, `CalibrationBehavior`: Enum values
- `Version`: `int`
- `TestChannelOrders`, `Tags`: `List<string>`
- Clock configuration properties: `ClockMasterInput`, `ClockMasterOutput`, `ManageClocksOutsideOfDataPROMaster`, etc.
- `SampleRateForDAS`, `DomainIdForDAS`, `IsClockMaster`: `Dictionary<string, ...>`
### `ServiceCall`
- **`bool Started`**
Indicates whether the call has been started.
- **`Action WorkAction`**
The work to execute.
- **`void MarkDone()`**
Signals completion by calling `ServiceQueue.MarkFinished(this)`.
- **`string Name`**
Human-readable identifier.
- **`ServiceCall(string name)`**
Constructor.
### `ServiceQueue`
- **`static void Enqueue(ServiceCall call)`**
Adds a `ServiceCall` to the queue. Starts execution immediately if queue was empty.
- **`static void MarkFinished(ServiceCall call)`**
Removes the call from the queue and starts the next queued call if any. Handles non-active calls (not at head) by simple removal.
### `TagAwareBase`
- **`enum TagTypes`**
`User`, `Group`, `Template`, `TestSetup`, `Sensors`, `SensorModels`
- **`abstract TagTypes TagType { get; }`**
Must be implemented by derived classes to specify tag type.
- **`byte[] TagsBlobBytes`**
Gets/sets `TagIDs` as a byte array (for DB storage). Logs exceptions on failure.
- **`int[] TagIDs`**
Gets/sets the list of tag IDs.
- **`void SetTagsFromCommaSeparatedString(string tagText, Tags.GetSqlCommandDelegate getSqlCommand)`**
Parses comma-separated tags and sets `TagIDs`.
- **`virtual void SetTags(string[] tagsText, Tags.GetSqlCommandDelegate getSqlCommand)`**
Adds tags to DB and updates `TagIDs`. Raises `OnPropertyChanged("TagIDs")`.
- **`string GetTagsAsCommaSeparatedString(Tags.GetSqlCommandDelegate getSqlCommand)`**
Returns tags as comma-separated string.
- **`virtual string[] GetTagsArray(Tags.GetSqlCommandDelegate getSqlCommand)`**
Returns tag text array.
- **`virtual bool TagCompatible(string tags, ...)`**
Checks if any tag in the provided comma-separated string matches current tags.
- **`virtual bool TagCompatible(int[] tags)`**
Checks if any tag ID in `tags` intersects with `TagIDs`.
- **`virtual bool HasIntersectingTag(int[] tags)`**
Returns `true` if `tags` and `TagIDs` share any ID.
- **`void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags, ...)`**
Sets tags and commits assignments.
- **`void Commit(int id, TagTypes tagType, ...)`**
Deletes existing tag assignments for the object, then inserts new assignments for `TagIDs`. Uses stored procedures `sp_TagAssignmentsDelete` and `sp_TagAssignmentsInsert`.
- **`List<int> GetTagIdList(int objectId, TagTypes tagType, ...)`**
Retrieves tag IDs for an object from DB via `sp_TagAssignmentsGet`. Logs failures.
### `Utility`
- **`static byte[] GetBytesFromStringArray(string[] array, string separator)`**
Joins array with `separator`, returns UTF-8 bytes.
- **`static string GetAllErrorMessages(Exception ex)`**
Recursively aggregates exception messages (including inner exceptions).
- **`static bool PingNetwork(string hostNameOrAddress)`**
Pings host with 4s timeout and fixed buffer. Returns `true` on success.
- **`static T GetX(IDataReader reader, string column, T defaultValue = default)`**
Generic pattern for safe column extraction:
- `GetUShort`, `GetUInt`, `GetString`, `GetStringArray`, `GetInt`, `GetDouble`, `GetShort`, `GetNullableDateTime`, `GetUlong`, `GetNullableInt`, `GetByteArray`, `GetBool`, `GetDateTime`, `GetLong`
All return `defaultValue` on `DBNull`, parse failure, or invalid column. Logs parse failures via `APILogger`.
### `Tags`
- **`class Tag`**
- `const int INVALID_ID = -1`
- `int ID`, `string Text`, `bool IsObsolete`
- Constructors: `(string, int)`, `(Tag)`, `(IDataRecord)`, `(DataRow)`
- `object Clone()``new Tag(this)`
- **`delegate SqlCommand GetSqlCommandDelegate(bool bNewConnection)`**
Factory for database commands.
- **`static Tags GetTagsInstance(GetSqlCommandDelegate getSqlCommand)`**
Gets singleton instance (lazy-initialized).
- **`static bool AddTag(string tagText, ...)`**
Adds tag to DB if not present. Returns `true` if added.
- **`static bool MigrateTag(string tagText, ...)`**
Commits tag (used for DB migration).
- **`static bool[] AddRange(string[] tagText, ...)`**
Adds multiple tags. Trims leading whitespace before adding.
- **`static int GetIDFromTagText(string tagText, ...)`**
Gets tag ID from DB (returns `Tag.INVALID_ID` if not found).
- **`static int[] GetIDsFromTagText(string[] tagText, ...)`**
Gets tag IDs for array of texts. Filters out `INVALID_ID`.
- **`static string GetTagTextFromID(int tagID, ...)`**
Gets tag text from memory cache (returns `null` if invalid/missing).
- **`static string[] GetTagTextFromIDs(int[] tagId, ...)`**
Gets tag texts from IDs. Filters invalid/whitespace.
- **`bool ContainsTag(string text)`**
Checks if tag exists in memory cache.
- **`void UpdateList(GetSqlCommandDelegate getSqlCommand)`**
Refreshes memory cache from DB via `sp_TagsGet`.
## 3. Invariants
- **Singleton<T>**:
- Only one instance per `T` exists. Attempting `new T()` throws `InvalidOperationException`.
- Static constructor exceptions are captured and rethrown on `Instance` access.
- **BulkObservableCollection<T>**:
- `AddRange`/`RemoveRange` fire exactly one `Reset` notification per call, regardless of item count.
- `CheckReentrancy()` is called before modifications to prevent reentrancy issues.
- **ServiceQueue**:
- Only one `ServiceCall` executes at a time (via `Task.Run`).
- Calls are processed in FIFO order.
- `MarkFinished` only advances the queue if the finished call is the head of the queue.
- **Tags**:
- Tags are immutable (no rename/delete/obsolete support).
- Memory cache (`_tagsLookup`) is lazily populated and updated only via `AddTag`, `MigrateTag`, or `UpdateList`.
- `Tag.INVALID_ID` (`-1`) is used to indicate missing tags.
- **TagAwareBase**:
- `TagIDs` is never `null` (defaults to `new int[0]`).
- `Commit` deletes existing assignments before inserting new ones.
## 4. Dependencies
- **Imports/References**:
- `Unity` (Microsoft Unity Container)
- `System.Windows` (`Color`, `Visibility`)
- `System.Data`, `System.Data.SqlClient` (ADO.NET)
- `DTS.Common.Base` (`BasePropertyChanged`, `IBaseViewModel`)
- `DTS.Common.Enums` (`RecordingModes`, `CalibrationBehaviors`, `InputClockSource`, `OutputClockSource`)
- `DTS.Common.Interface.Sensors` (`ISensor`)
- `DTS.Common.Utilities.Logging` (`APILogger`)
- **Depended upon by**:
- UI layers (via `RegionNames`, `StatusAndProgressBarEventArgs`)
- Data import modules (`ImportData`)
- Service orchestration consumers (`ServiceQueue`)
- Tag-aware entities (`TagAwareBase`)
- Database access layers (`Utility`, `Tags`)
## 5. Gotchas
- **`Singleton<T>`**:
- Static initialization exceptions are logged to `Console.WriteLine` (not `APILogger`).
- The singleton instance is created on first `Instance` access, not on module load.
- **`BulkObservableCollection<T>`**:
- `AddRange`/`RemoveRange` use `NotifyCollectionChangedAction.Reset`, which may cause UI controls to re-render entirely (not incremental updates).
- Exceptions in `AddRange`/`RemoveRange` are silently logged and do not propagate.
- **`ServiceQueue`**:
- `ServiceCall.Started` is used to prevent duplicate execution, but there is no cancellation mechanism.
- Non-active calls (not at head) are removed from the queue without execution.
- **`Tags`**:
- Memory cache (`_tagsLookup`) is *not* automatically updated after `AddTag`/`MigrateTag` (only updated on `UpdateList` or explicit `Commit`).
- `GetTagTextFromID` reads from cache only; if cache is stale, it may return `null` for valid IDs.
- **`TagAwareBase`**:
- `RemoveTags` is a stub (empty implementation).
- `SetTagsFromCommaSeparatedString` does *not* skip empty strings (despite commented-out null check referencing FogBugz #7176).
- **`Utility`**:
- `PingNetwork` uses a fixed 32-byte buffer and 4-second timeout.
- All `GetX` methods return `defaultValue` on parse failure without rethrowing.
- **`ImportData.TestSetupImportData`**:
- Clock master/slave properties (`ClockMasterInput`, `ClockMasterOutput`, etc.) default to `None` and `false`.