--- source_files: - Common/DTS.Common.Serialization/TestSetup/Graph/Graph.cs - Common/DTS.Common.Serialization/TestSetup/Graph/Channel.cs generated_at: "2026-04-16T03:41:07.285794+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "54ff68752851044a" --- # Graph ## Documentation: `DTS.Serialization.Graph` and `DTS.Serialization.Graph.Channel` --- ### 1. **Purpose** This module defines core serialization-friendly data structures (`Graph` and `Channel`) used to represent test setup configurations in the DTS (Dynamic Test System) framework. The `Graph` class encapsulates a test configuration as a named, versioned container of one or more `Channel` instances, each representing a logical test channel tied to either a live `Test.Module.Channel` object or a placeholder for deserialization scenarios. These classes are designed for XML serialization (evidenced by use of `XmlIgnoreAttribute`) and serve as a lightweight, serializable abstraction layer over the richer, runtime `Test.Module` domain model—enabling persistence, transmission, or reconstruction of test setups without coupling to the full test execution engine. --- ### 2. **Public Interface** #### `DTS.Serialization.TestSetup.Graph` - **`Graph()`** Default constructor. Initializes `_Version.Value` to `"1.0.0.0"`, sets `_Name.Value` to `null`, and assigns a new `Guid` to `Identifier`. - **`void UnSet()`** No-op method (empty implementation). Purpose unclear from source. - **`List Channels { get; set; }`** Gets or sets the list of channels in this graph. Initialized to an empty list by default. - **`string Name { get; set; }`** Gets or sets the graph’s logical name. Defaults to `""`. - **`string HardwareChannelName { get; set; }`** Gets or sets a hardware-specific channel name (e.g., physical port label). Defaults to `""`. - **`string DisplayName { get; }`** Computed property: concatenates `Name` and `HardwareChannelName` with an underscore (`Name + "_" + HardwareChannelName`). May yield `"_"` if both are empty. - **`string Version { get; set; }`** Gets or sets the graph version string. *Note:* Constructor sets `_Version.Value = "1.0.0.0"`, but the backing field `_Version` is initialized with `""` as default—this is overwritten in the constructor. - **`override string ToString()`** Returns `Name`. - **`bool IsSingleChannelGraph { get; }`** Returns `true` if `Channels` is non-null and contains exactly one element. - **`Channel FirstChannel { get; }`** Returns the first element in `Channels`. **Unsafe**: throws `IndexOutOfRangeException` if `Channels` is null or empty. - **`Test.Module.Channel FirstTestChannel { get; }`** Returns `FirstChannel.TestChannel`. **Unsafe**: throws `IndexOutOfRangeException` if `Channels` is null/empty, or `NullReferenceException` if `FirstChannel.TestChannel` is null. - **`Guid Identifier { get; private set; }`** Unique identifier for the graph instance. Set only in constructor via `Guid.NewGuid()`. #### `DTS.Serialization.TestSetup.Graph.Channel` - **`Channel()`** *(private)* Internal constructor. Sets `ChannelId = "Not Set"`. Not used externally. - **`Channel(Test.Module.Channel channel)`** Constructor for wrapping an existing runtime `Test.Module.Channel`. Populates: - `ParentTestModule` = `channel.ParentModule` - `TestChannel` = `channel` - `ChannelId` = `channel.ChannelId` - `ChannelGroupName` = `channel.ChannelGroupName` *Note:* A `TODO` comment indicates intent to use a unique key (e.g., `Identifier`) instead of `HardwareChannelName`—but this is not implemented. - **`Channel(string channelId)`** Constructor for placeholder channel (e.g., deserialization). Sets `ParentTestModule = null`, `TestChannel = null`, and `ChannelId = channelId`. - **`Channel(long groupChannelId)`** Constructor for placeholder channel from numeric ID. Sets `ParentTestModule = null`, `TestChannel = null`, and `ChannelId = groupChannelId.ToString()`. - **`override string ToString()`** Returns `TestChannel.ToString()` if `TestChannel` is non-null; otherwise `"Not Set"`. - **`string ChannelId { get; set; }`** Logical channel identifier (e.g., `"TestObjectSerial_ChannelType_ChannelId"`). Used as a unique key *in practice*, though not enforced. - **`string ChannelGroupName { get; set; }`** Group name for the channel (e.g., `"Axial"`, `"Radial"`). - **`string Name { get; }`** Returns `TestChannel.ChannelDescriptionString` if `TestChannel` is non-null; otherwise `"Not Set"`. - **`string SensorName { get; }`** Returns `TestChannel.ChannelDescriptionString.ToString()` if `TestChannel` is non-null; otherwise `"Not Set"`. *Note:* Redundant with `Name`; likely legacy or for XML serialization compatibility. - **`string AxisUnit { get; }`** Returns engineering units (`AnalogInputChannel.EngineeringUnits`) if `TestChannel` is an `AnalogInputChannel`; otherwise `"EU"`. - **`string SerialNumber { get; }`** Returns `ParentTestModule.SerialNumber` if `ParentTestModule` is non-null; otherwise `"Not Set"`. - **`Test.Module ParentTestModule;`** Public field referencing the parent test module (e.g., sensor or DAQ device). May be `null` for placeholder channels. - **`Test.Module.Channel TestChannel;`** Public field referencing the underlying runtime channel object. May be `null` for placeholder channels. --- ### 3. **Invariants** - **`Graph.Identifier`** is assigned exactly once during construction and never modified afterward. - **`Graph.Channels`** is never `null` after construction (initialized to `new List()` in `_Channels`). - **`Graph.Version`** is initialized to `"1.0.0.0"` in the constructor, overriding the default `""` in `_Version`. - **`Channel.ChannelId`** is always set (non-null) and used as a logical identifier, though uniqueness is not enforced by the class. - **`Graph.DisplayName`** may be malformed (e.g., `"_"`, `"_" + HardwareChannelName`) if `Name` is empty or whitespace. - **`Graph.FirstChannel`** and **`Graph.FirstTestChannel`** assume `Channels.Count >= 1`; no bounds checking is performed. --- ### 4. **Dependencies** - **Internal Dependencies**: - `DTS.Common.Utilities` (namespace) - `DTS.Common.Utilities.DotNetProgrammingConstructs` (for `Property` wrapper) - `System`, `System.Collections.Generic`, `System.Xml.Serialization` - **External Dependencies**: - `Test.Module` (namespace): referenced via `Test.Module.Channel`, `Test.Module.ParentTestModule`, `Test.Module.AnalogInputChannel`, and `Test.Module.Channel.ChannelDescriptionString`. *This implies a hard dependency on the `Test.Module` assembly (likely `DTS.TestModule.dll` or similar).* - `Exceptional`: Base class for both `Graph` and `Channel` (inherited from `TestSetup.Exceptional`). - **Depended Upon By**: - Serialization infrastructure (e.g., XML serializers, given `[XmlIgnore]` usage). - Test setup persistence layers (e.g., saving/loading `.xml` test configurations). - UI or tooling that consumes serialized test setups. --- ### 5. **Gotchas** - **`Graph.FirstChannel` and `Graph.FirstTestChannel` are unsafe**: No null/empty checks—accessing them on an empty `Channels` list will throw `IndexOutOfRangeException`. - **`DisplayName` may produce misleading output**: Concatenation of `Name` and `HardwareChannelName` without trimming or validation can yield `"_"` or `"Name_"`. - **`Channel` constructors are inconsistent in initialization**: - `Channel(Test.Module.Channel)` populates `ParentTestModule` and `TestChannel`. - `Channel(string)` and `Channel(long)` leave them `null`. Code must check for null `TestChannel`/`ParentTestModule` before accessing derived properties (`Name`, `SerialNumber`, etc.). - **`SensorName` duplicates `Name` logic**: Both use `TestChannel.ChannelDescriptionString`, but `SensorName` calls `.ToString()` explicitly—likely redundant or legacy. - **`HardwareChannelName` is unused in `Channel` constructor**: The `TODO` comment suggests `Identifier` should be set from `HardwareChannelName`, but this is not implemented. `Identifier` remains `Guid.NewGuid()` (graph-level), while `Channel` has no `Identifier` field. - **`Channel` has no `Identifier` field**: Unlike `Graph`, `Channel` lacks a unique ID—relying on `ChannelId` (a string) as a de facto key, but this is not enforced or validated. - **`UnSet()` is a no-op**: Its purpose is unclear; may be a placeholder for future cleanup or legacy pattern. - **`Property` behavior**: The `Property` wrapper (from `DotNetProgrammingConstructs`) likely handles change notifications or serialization metadata, but its exact semantics (e.g., null handling, validation) are not visible here. Default values (`""`, `new List()`) are set in field initializers, but constructor overrides (e.g., `Version = "1.0.0.0"`) may conflict with expectations.