Files
2026-04-17 14:55:32 -04:00

8.9 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common.Serialization/Test/Module/IConvertable.cs
Common/DTS.Common.Serialization/Test/Module/CalculatedChannel.cs
2026-04-16T03:40:25.931280+00:00 Qwen/Qwen3-Coder-Next-FP8 1 ac5cc711621ec54b

Module

Documentation Page: DTS.Serialization.Test.Module.IConvertable and DTS.Serialization.Test.Module.CalculatedChannel


1. Purpose

This module provides serialization infrastructure and a concrete implementation for handling calculated channels in the DTS test data model. Specifically, the IConvertable interface defines a contract for objects that can be converted to/from the internal Test.Module serialization format, enabling interoperability with external or legacy serialization layers. The CalculatedChannel class implements this interface (via inheritance from AnalogInputChannel, which presumably implements IConvertable) and represents a derived channel whose values are computed from one or more source channels using a user-defined formula. It supports XML serialization/deserialization with custom attribute tagging and array-based source channel/module metadata.


2. Public Interface

IConvertable Interface (Nested in Test.Module)

  • Module ToDtsSerializationTestModule(Test parentTest)
    Converts the implementing object into a Test.Module instance. The parentTest parameter identifies the containing test context.

  • void FromDtsSerializationTestModule(Module testModule, ReportErrors reportErrors)
    Initializes the implementing object from a Test.Module instance. The reportErrors delegate is used to surface validation or parsing errors encountered during deserialization.

Note

: The interface is declared in IConvertable.cs, but its implementation is not shown in the provided source. The CalculatedChannel class inherits from AnalogInputChannel, which is assumed to implement IConvertable.

CalculatedChannel Class (Nested in Test.Module)

  • CalculatedChannel(Module parentModule)
    Constructor. Initializes a new CalculatedChannel instance with the given parent module.

  • int[] SourceChannelNumber { get; set; }
    Gets/sets the array of channel numbers from which this calculated channel derives its data.

  • int[] SourceModuleNumber { get; set; }
    Gets/sets the array of module numbers corresponding to each source channel.

  • string[] SourceModuleSerialNumber { get; set; }
    Gets/sets the array of serial numbers for the modules containing the source channels.

  • string Calculation { get; set; }
    Gets/sets the calculation expression (e.g., "A + B * 2") applied to the source channels. Default: "NONE".

  • ulong T1 { get; set; }
    Gets/sets a time parameter (likely for HIC calculations). Default: 0.

  • ulong T2 { get; set; }
    Gets/sets a second time parameter (likely for HIC calculations). Default: 0.

  • double HIC { get; set; }
    Gets/sets the Head Injury Criterion value (a derived metric). Default: 0.0.

  • double SampleRateHz { get; set; }
    Gets/sets the sample rate (in Hz) for this calculated channel. Inherited from base class or set explicitly.

  • override void WriteXml(XmlWriter writer)
    Serializes the object to XML. Writes attributes for all public properties (including SourceChannelNumber, SourceModuleNumber, SourceModuleSerialNumber, Calculation, SampleRateHz, and conditionally HIC, T1, T2). Uses AttributeExtractor<XmlSerializationTagAttribute> to resolve XML tag names.

  • override void ReadXml(XmlReader reader)
    Deserializes the object from XML. Reads attributes using PropertyAttributeDecoder<CalculatedChannel>. Handles parsing of comma-separated integer arrays (SourceChannelNumber, SourceModuleNumber) and custom-delimited string arrays (SourceModuleSerialNumber, using "_.-._" as delimiter).

  • static CalculatedChannel CreateInstance(Channel[] channels)
    Factory method to create a CalculatedChannel from multiple source Channels. Validates that the maximum sample rate is a multiple of each source channels sample rate. Copies all properties from the first channel using TypeDescriptor. Initializes SourceChannelNumber, SourceModuleNumber, and SourceModuleSerialNumber arrays from all input channels.

  • static CalculatedChannel CreateInstance(Channel sourceChannel)
    Factory method to create a CalculatedChannel from a single Channel. Sets SourceChannelNumber, SourceModuleNumber, and SourceModuleSerialNumber to single-element arrays derived from the source channel.

  • override bool Equals(object obj)
    Performs memberwise equality comparison with another CalculatedChannel. Compares: ChannelId, SourceChannelNumber, ChannelDescriptionString, EngineeringUnits (case-insensitive), Calculation, and IsoCode.

  • override int GetHashCode()
    Returns the hash code from the base class (no custom logic visible).

  • override string ToString()
    Returns ChannelDescriptionString.


3. Invariants

  • Array Length Consistency: For SourceChannelNumber, SourceModuleNumber, and SourceModuleSerialNumber, all three arrays must have identical length. This is enforced by convention in CreateInstance, but not validated in ReadXml/WriteXml.
  • Sample Rate Compatibility: In CreateInstance(Channel[]), the maximum sample rate among source channels must be an integer multiple of each source channels sample rate; otherwise, an InvalidOperationException is thrown.
  • Optional Fields: HIC, T1, and T2 are only serialized if _HIC.IsValueInitialized is true. This implies they are initialized conditionally (e.g., only when non-zero or explicitly set).
  • Default Values: Calculation defaults to "NONE", SampleRateHz defaults to 0, numeric arrays default to null, and HIC/T1/T2 default to 0/0U/0U.
  • Serialization Format:
    • Integer arrays are comma-separated (e.g., "1,2,3").
    • String arrays use "_.-._" as a delimiter (e.g., "SN1_.-._SN2_.-._SN3").
    • XML attributes use tags defined by [XmlSerializationTag(...)] attributes.

4. Dependencies

Module Dependencies

  • DTS.Common.Utilities.Xml.AttributeExtractor<T>
    Used in WriteXml to extract XML tag names from attributes.
  • DTS.Common.Utilities.Xml.PropertyAttributeDecoder<T>
    Used in ReadXml to decode XML attributes into properties.
  • DTS.Common.Utilities.Logging.APILogger
    Used for logging in WriteXml and ReadXml.
  • System.ComponentModel.TypeDescriptor
    Used in CreateInstance to copy property values via reflection.
  • DTS.Common.Classes.Sensors.LinearizationFormula
    Used in CreateInstance(Channel[]) to clone the linearization formula.

Inferred Dependencies

  • AnalogInputChannel (base class of CalculatedChannel) must implement IConvertable, though its implementation is not shown here.
  • Test and Module classes are nested containers (see namespace structure).
  • ReportErrors delegate type is referenced in IConvertable.FromDtsSerializationTestModule but not defined in the provided source.

5. Gotchas

  • Array Delimiter Ambiguity: The string array delimiter "_.-._" is not documented in comments and may conflict with legitimate serial numbers containing that substring. No escaping or quoting is applied.
  • Partial Initialization in ReadXml: HIC, T1, and T2 are only deserialized if the HIC attribute is present and non-whitespace. If only T1/T2 are present, they will remain at default (0), potentially masking incomplete data.
  • Sample Rate Validation Only in Factory: The sample rate divisibility check occurs only in CreateInstance(Channel[]), not during XML deserialization or direct property assignment. Invalid rates may be silently stored.
  • Property Copying via Reflection: CreateInstance uses TypeDescriptor.GetProperties to copy properties. This may fail silently for properties that throw exceptions during GetValue/SetValue (exceptions are logged or swallowed).
  • No Deep Clone for LinearizationFormula: The LinearizationFormula is cloned via constructor, but other reference-type properties (e.g., LinearizationFormula is the only one explicitly cloned) may be shared if not handled.
  • Case-Insensitive Comparison Only for EngineeringUnits: The Equals method uses StringComparison.OrdinalIgnoreCase for EngineeringUnits, but other string properties (Calculation, ChannelDescriptionString, IsoCode) use case-sensitive comparison—this inconsistency may cause confusion.
  • SourceModuleNumber Not Populated in Factories: In both CreateInstance overloads, SourceModuleNumber is initialized as an empty array (moduleNumbers is never populated), which is likely a bug.

Note

: The ReportErrors delegate signature and AnalogInputChannels implementation of IConvertable are not visible in the provided source. Their behavior is inferred.