init
This commit is contained in:
175
enriched-qwen3-coder-next/Common/DTS.CommonCore/Base/Classes.md
Normal file
175
enriched-qwen3-coder-next/Common/DTS.CommonCore/Base/Classes.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Base/Classes/BasePropertyChanged.cs
|
||||
- Common/DTS.CommonCore/Base/Classes/DisplayResourceAttribute.cs
|
||||
- Common/DTS.CommonCore/Base/Classes/DescriptionResourceAttribute.cs
|
||||
- Common/DTS.CommonCore/Base/Classes/DynamicTypeDescriptor.cs
|
||||
generated_at: "2026-04-16T02:51:28.846308+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e84e534d3f8838df"
|
||||
---
|
||||
|
||||
# Classes
|
||||
|
||||
## Documentation: `DTS.Common.Base` Module – Property Change Notification & Dynamic Type Descriptor Infrastructure
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides foundational infrastructure for property change notification and dynamic runtime customization of object metadata—primarily to support UI frameworks like `PropertyGrid` where static attributes (e.g., `DisplayName`, `Description`) must be overridden or extended at runtime. It includes a base class (`BasePropertyChanged`) for implementing `INotifyPropertyChanged`, and two custom attribute classes (`DisplayResourceAttribute`, `DescriptionResourceAttribute`) that delegate display strings to localized resources via `Strings.Strings.ResourceManager`. Additionally, `DynamicTypeDescriptor` enables dynamic modification of property metadata (e.g., browsability, display name, category) for objects, especially useful for types like Entity Framework proxies where attributes cannot be applied directly.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `BasePropertyChanged`
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Virtual event for property change notifications. Subclasses may override to customize notification behavior.
|
||||
|
||||
- **`bool SetProperty<T>(ref T storage, T value, string propertyName = null)`**
|
||||
Compares `storage` and `value` for equality; if different, updates `storage`, invokes `OnPropertyChanged`, and returns `true`. Returns `false` if values are equal. Used to implement `INotifyPropertyChanged` concisely.
|
||||
|
||||
- **`virtual void OnPropertyChanged(string propertyName = null)`**
|
||||
Raises the `PropertyChanged` event with the given property name. If `propertyName` is `null`, raises `PropertyChangedEventArgs.Empty`.
|
||||
|
||||
#### `DisplayResourceAttribute`
|
||||
- **`DisplayResourceAttribute(string resourceId)`**
|
||||
Constructor. Stores `resourceId` for later lookup in `Strings.Strings.ResourceManager`.
|
||||
|
||||
- **`override string DisplayName`**
|
||||
Returns the localized string from `Strings.Strings.ResourceManager.GetString(resourceId)`, or `"##ResourceNotFound##" + resourceId` if not found.
|
||||
|
||||
#### `DescriptionResourceAttribute`
|
||||
- **`DescriptionResourceAttribute(string resourceId)`**
|
||||
Constructor. Stores `resourceId` for later lookup in `Strings.Strings.ResourceManager`.
|
||||
|
||||
- **`override string Description`**
|
||||
Returns the localized string from `Strings.Strings.ResourceManager.GetString(resourceId)`, or `"##DescriptionNotFound##" + resourceId` if not found.
|
||||
|
||||
#### `DynamicTypeDescriptor`
|
||||
- **`DynamicTypeDescriptor(Type type)`**
|
||||
Constructor. Initializes internal state by querying `TypeDescriptor` for the given `type`. Filters out non-browsable properties. Stores original properties, type converter, default event/property, and editors.
|
||||
|
||||
- **`T GetPropertyValue<T>(string name, T defaultValue)`**
|
||||
Retrieves the value of the property named `name` from the current `Component`, casting to `T`. Returns `defaultValue` on failure or if property not found.
|
||||
|
||||
- **`void SetPropertyValue(string name, object value)`**
|
||||
Sets the value of the property named `name` on the current `Component`. No-op if property not found.
|
||||
|
||||
- **`DynamicProperty AddProperty(Type type, string name, object value, string displayName, string description, string category, bool hasDefaultValue, object defaultValue, bool readOnly, Type uiTypeEditor)`**
|
||||
Creates and adds a new `DynamicProperty` with specified metadata. Overload omits `uiTypeEditor` (defaults to `null`).
|
||||
|
||||
- **`void AddProperty(PropertyDescriptor property)`**
|
||||
Adds a pre-constructed `PropertyDescriptor` (e.g., `DynamicProperty`) to the `Properties` collection.
|
||||
|
||||
- **`void RemoveProperty(string name)`**
|
||||
Removes the property named `name` from the `Properties` collection.
|
||||
|
||||
- **`DynamicTypeDescriptor FromComponent(object component)`**
|
||||
Creates a new `DynamicTypeDescriptor` instance bound to `component`, copying original metadata and creating `DynamicProperty` wrappers for each property. Requires `component` to be assignable to the original `_type`.
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Implements `INotifyPropertyChanged`. Raised internally via `OnValueChanged(PropertyDescriptor)` when a property value changes.
|
||||
|
||||
- **`PropertyDescriptorCollection Properties { get; }`**
|
||||
Mutable collection of *browsable* properties (original + dynamically added/modified). Non-browsable properties are excluded during construction.
|
||||
|
||||
- **`PropertyDescriptorCollection OriginalProperties { get; }`**
|
||||
Immutable snapshot of the original properties (including non-browsable ones) as returned by `TypeDescriptor.GetProperties(type)`.
|
||||
|
||||
- **`object Component { get; }`**
|
||||
The object instance whose properties are being described. Set only during `FromComponent`.
|
||||
|
||||
- **`string ClassName { get; set; }` / `string ComponentName { get; set; }`**
|
||||
Overridable display names for the type and component, respectively, used in `ICustomTypeDescriptor.GetClassName()`/`GetComponentName()`.
|
||||
|
||||
#### `DynamicTypeDescriptor.DynamicProperty`
|
||||
- **`DynamicProperty(DynamicTypeDescriptor descriptor, Type type, object value, string name, Attribute[] attrs)`**
|
||||
Internal constructor for a new dynamic property (not tied to an existing property descriptor).
|
||||
|
||||
- **`DynamicProperty(DynamicTypeDescriptor descriptor, PropertyDescriptor existing, object component)`**
|
||||
Internal constructor wrapping an *existing* property descriptor, capturing its value and attributes.
|
||||
|
||||
- **`void SetDisplayName(string displayName)` / `void SetDescription(string description)` / `void SetCategory(string category)`**
|
||||
Overrides the corresponding property metadata (e.g., `DisplayName`, `Description`, `Category`) for this dynamic property.
|
||||
|
||||
- **`void SetBrowsable(bool browsable)` / `void SetIsReadOnly(bool readOnly)`**
|
||||
Overrides `IsBrowsable` and `IsReadOnly` behavior.
|
||||
|
||||
- **`void RemoveAttributesOfType<T>()`**
|
||||
Removes all attributes of type `T` (or derived) from the internal `_attributes` list.
|
||||
|
||||
- **`IList<Attribute> AttributesList { get; }`**
|
||||
Exposes the internal list of attributes for inspection/modification.
|
||||
|
||||
- **`override object GetValue(object component)` / `override void SetValue(object component, object value)`**
|
||||
Gets/sets the property value. If wrapping an `_existing` property, delegates to it; otherwise uses the internal `Value` field.
|
||||
|
||||
- **`override void ResetValue(object component)`**
|
||||
Resets value to default (if `_existing` exists, delegates; otherwise uses `_defaultValue` or `Value`).
|
||||
|
||||
- **`override bool IsBrowsable` / `override bool IsReadOnly` / `override string DisplayName` / `override string Description` / `override string Category`**
|
||||
Returns overridden values if set; otherwise falls back to base implementation or wrapped `_existing` property.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **`BasePropertyChanged.SetProperty`**
|
||||
- Only raises `PropertyChanged` if `storage` and `value` are *not* equal (via `Equals`).
|
||||
- `storage` is updated *before* `OnPropertyChanged` is called.
|
||||
|
||||
- **`DynamicTypeDescriptor`**
|
||||
- `Properties` collection excludes non-browsable properties *at construction time* (via `if (!property.IsBrowsable) continue;`).
|
||||
- `FromComponent` performs a *shallow copy* of internal state (e.g., `_editors`, `_typeConverter`), but creates *new* `DynamicProperty` instances per property.
|
||||
- `DynamicProperty` overrides metadata *only if explicitly set* via `Set*` methods; otherwise falls back to original or base behavior.
|
||||
- `DynamicTypeDescriptor` implements `ICustomTypeDescriptor` and `INotifyPropertyChanged`—consumers may rely on both interfaces.
|
||||
|
||||
- **`DisplayResourceAttribute` / `DescriptionResourceAttribute`**
|
||||
- `DisplayName`/`Description` always returns a non-null string: either the localized value or a fallback marker (`##ResourceNotFound##`/`##DescriptionNotFound##`) concatenated with the `resourceId`.
|
||||
- Resource lookup uses `Strings.Strings.ResourceManager.GetString(resourceId)`—*no* automatic suffixing (e.g., `"PropertyName_Description"` must be the exact `resourceId` passed to the constructor).
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Internal Dependencies**
|
||||
- `System.ComponentModel` (`INotifyPropertyChanged`, `PropertyChangedEventHandler`, `Attribute`, `PropertyDescriptor`, etc.).
|
||||
- `Strings.Strings.ResourceManager` (from `DTS.Common` resources) for `DisplayResourceAttribute` and `DescriptionResourceAttribute`.
|
||||
- `System.Drawing.Design` (`UITypeEditor`, `EditorAttribute`) for editor support in `DynamicTypeDescriptor`.
|
||||
|
||||
- **External Dependencies**
|
||||
- `DynamicTypeDescriptor` is used by UI components (e.g., `PropertyGrid`) that rely on `ICustomTypeDescriptor`.
|
||||
- `BasePropertyChanged` is intended for use by view models or entities requiring `INotifyPropertyChanged`.
|
||||
- `DisplayResourceAttribute`/`DescriptionResourceAttribute` are used as attributes on properties to enable localization.
|
||||
|
||||
- **Inferred Usage**
|
||||
- Likely consumed by UI layers (e.g., WinForms `PropertyGrid`, WPF data binding) where dynamic metadata or localization is needed.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **`DynamicTypeDescriptor` does *not* automatically propagate changes to the underlying `Component`** when using `DynamicProperty` with no `_existing` property. `SetValue`/`ResetValue` only update the internal `Value` field of the `DynamicProperty`. To bind to real properties, use `FromComponent` to wrap an existing property descriptor.
|
||||
|
||||
- **`DynamicProperty.Attributes` is a *snapshot* of `_attributes` at construction time** unless modified via `RemoveAttributesOfType<T>` or `Set*` methods. Direct mutation of `_attributes` is not exposed.
|
||||
|
||||
- **`DisplayResourceAttribute` and `DescriptionResourceAttribute` do *not* support fallback to property name**—if the resource ID is missing, the marker string (`##ResourceNotFound##`/`##DescriptionNotFound##`) is returned *as-is*, including the ID. This may cause UI clutter if not handled.
|
||||
|
||||
- **`BasePropertyChanged.SetProperty` uses `Equals` for comparison**, which may be unsafe for mutable reference types (e.g., collections). Consider using `EqualityComparer<T>.Default` or custom comparison if needed.
|
||||
|
||||
- **`DynamicTypeDescriptor` filters properties by `IsBrowsable` at construction time**, so non-browsable properties (e.g., `DesignerSerializationVisibility.Hidden`) are permanently excluded from `Properties`. Use `OriginalProperties` to inspect all properties.
|
||||
|
||||
- **`DynamicTypeDescriptor.FromComponent` requires `component.GetType()` to be assignable to `_type`**. Passing a derived type may throw `ArgumentException`.
|
||||
|
||||
- **`DynamicProperty`’s `ShouldSerializeValue` always returns `false` unless wrapping an `_existing` property**—this may interfere with serialization logic expecting `ShouldSerialize*` semantics.
|
||||
|
||||
- **No thread-safety guarantees** are documented or implied for `DynamicTypeDescriptor` or `BasePropertyChanged`. Concurrent access to `Properties` or `PropertyChanged` events may require external synchronization.
|
||||
|
||||
- **`Strings.Strings.ResourceManager` must be initialized before `DisplayResourceAttribute`/`DescriptionResourceAttribute` are instantiated**, or `GetString` will return `null`. This is a runtime dependency on the application’s localization setup.
|
||||
|
||||
---
|
||||
|
||||
*Documentation generated from source files only. No external behavior or assumptions beyond the provided code.*
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseClass.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IViewModel.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseView.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseWindow.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseModel.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBasePropertyChanged.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IHeaderInfoProvider.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseWindowModel.cs
|
||||
- Common/DTS.CommonCore/Base/Interface/IBaseViewModel.cs
|
||||
generated_at: "2026-04-16T02:50:59.182890+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "cd583516ecde421b"
|
||||
---
|
||||
|
||||
# Interface
|
||||
|
||||
## Documentation: DTS.Common.Base Interface Layer
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module defines a foundational set of interfaces for implementing the Model-View-ViewModel (MVVM) pattern within the DTS codebase. It establishes contract-based abstractions for core UI and data entities—`IBaseModel`, `IBaseViewModel`, `IBaseWindowModel`, `IBaseView`, `IBaseWindow`, and supporting interfaces like `IBasePropertyChanged` and `IHeaderInfoProvider<T>`—to enforce consistency, lifecycle management, and property change notification across the application. These interfaces decouple UI components (Views/Windows) from their backing logic (ViewModels/Models), enabling testability, reuse, and standardized behavior for state tracking (`IsDirty`, `IsBusy`, `IsSaved`), initialization, and cleanup.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### Interfaces (all in `DTS.Common.Base` namespace)
|
||||
|
||||
| Interface | Signature | Description |
|
||||
|-----------|-----------|-------------|
|
||||
| `IBaseClass` | `public interface IBaseClass : IBasePropertyChanged { }` | Marker interface extending `IBasePropertyChanged`. Used as a base contract for classes requiring property change notification. |
|
||||
| `IBasePropertyChanged` | `public interface IBasePropertyChanged : INotifyPropertyChanged { void OnPropertyChanged(string propertyName); }` | Extends `INotifyPropertyChanged` with a required `OnPropertyChanged(string)` method. *Note: No default implementation is provided.* |
|
||||
| `IBaseModel` | `public interface IBaseModel : IBasePropertyChanged { bool IsSaved { get; } }` | Base interface for domain models. Guarantees `IsSaved` read-only state (e.g., whether the model has unsaved changes). |
|
||||
| `IBaseViewModel` | `public interface IBaseViewModel : IBasePropertyChanged { ... }` | Base interface for ViewModels. Includes lifecycle methods (`Initialize`, `Activated`, `Cleanup`, `CleanupAsync`, `InitializeAsync`) and state properties (`IsMenuIncluded`, `IsNavigationIncluded`, `IsBusy`, `IsDirty`). Supports multiple `Initialize` overloads (with/without `parameter`, and with `parameter` + `model`). |
|
||||
| `IBaseWindowModel` | `public interface IBaseWindowModel : INotifyPropertyChanged { ... }` | Base interface for Window-level ViewModels. Mirrors `IBaseViewModel` but **does not inherit `IBasePropertyChanged`** (directly implements `INotifyPropertyChanged`). Includes identical lifecycle/state members. |
|
||||
| `IViewModel` | `public interface IViewModel { object Model { get; set; } }` | Minimal interface for ViewModels to expose their backing `Model`. Does not enforce lifecycle or state properties. |
|
||||
| `IBaseView` | `public interface IBaseView { object DataContext { get; set; } }` | Base interface for Views (e.g., UserControls). Declares `DataContext` for binding to a ViewModel. |
|
||||
| `IBaseWindow` | `public interface IBaseWindow { object DataContext { get; set; } }` | Base interface for Window classes. Declares `DataContext` for binding to a Window-level ViewModel. |
|
||||
| `IHeaderInfoProvider<T>` | `public interface IHeaderInfoProvider<T> { T HeaderInfo { get; } }` | Generic interface for objects that expose a `HeaderInfo` (e.g., for XAML binding to UI headers). Type parameter `T` specifies the `HeaderInfo` type. |
|
||||
|
||||
**Lifecycle Method Overloads Summary**
|
||||
All `Initialize`/`Cleanup` methods are defined in both `IBaseViewModel` and `IBaseWindowModel`:
|
||||
|
||||
- `void Initialize();`
|
||||
- `void Initialize(object parameter);`
|
||||
- `void Initialize(object parameter, object model);` *(only in `IBaseViewModel`)*
|
||||
- `Task InitializeAsync();`
|
||||
- `Task InitializeAsync(object parameter);`
|
||||
- `void Activated();`
|
||||
- `void Cleanup();`
|
||||
- `Task CleanupAsync();`
|
||||
|
||||
**State Properties**
|
||||
Shared across `IBaseViewModel` and `IBaseWindowModel`:
|
||||
|
||||
- `bool IsMenuIncluded { get; set; }`
|
||||
- `bool IsNavigationIncluded { get; set; }`
|
||||
- `bool IsBusy { get; set; }`
|
||||
- `bool IsDirty { get; }` *(read-only)*
|
||||
- `bool IsSaved { get; }` *(only in `IBaseModel`)*
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Property Change Notification**: Any class implementing `IBasePropertyChanged` (including `IBaseClass`, `IBaseModel`, `IBaseViewModel`) **must** raise `PropertyChanged` via `OnPropertyChanged(string propertyName)`. The interface does *not* enforce thread-safety or throttling—consumers must handle this.
|
||||
- **`IsDirty` vs `IsSaved`**:
|
||||
- `IsDirty` (in `IBaseViewModel`/`IBaseWindowModel`) indicates whether the ViewModel has unsaved changes *relative to its initialization state*.
|
||||
- `IsSaved` (in `IBaseModel`) indicates whether the underlying Model has been persisted.
|
||||
These are orthogonal: a model can be `IsSaved=true` but `IsDirty=true` if the ViewModel has made new changes since the last save.
|
||||
- **Lifecycle Order**:
|
||||
`Initialize`/`InitializeAsync` → `Activated` → (user interaction) → `Cleanup`/`CleanupAsync`.
|
||||
`InitializeAsync` and `CleanupAsync` are asynchronous; callers must await them to ensure completion before proceeding.
|
||||
- **`IHeaderInfoProvider<T>`**: The `HeaderInfo` property is read-only (`get` only). Implementations must ensure `HeaderInfo` is non-null (or handle null gracefully) for XAML binding.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### Dependencies *of this module*:
|
||||
- **`System.ComponentModel`**: Required for `INotifyPropertyChanged` (used in `IBasePropertyChanged`, `IBaseWindowModel`, `IBaseViewModel`).
|
||||
- **`System.Threading.Tasks`**: Required for `Task` return types in `IBaseViewModel` and `IBaseWindowModel`.
|
||||
|
||||
#### Dependencies *on this module* (inferred from naming conventions and usage patterns):
|
||||
- **UI Layer**: Views (e.g., WPF `Window`, `UserControl`) likely implement `IBaseView`/`IBaseWindow` and bind `DataContext` to ViewModels implementing `IBaseViewModel`/`IBaseWindowModel`.
|
||||
- **ViewModel Layer**: Concrete ViewModels inherit from base classes implementing `IBaseViewModel` or `IBaseWindowModel`.
|
||||
- **Model Layer**: Domain models likely implement `IBaseModel`.
|
||||
- **Header Binding**: UI components (e.g., headers, toolbars) consume types implementing `IHeaderInfoProvider<T>`.
|
||||
|
||||
#### No internal dependencies *within* this module (interfaces are self-contained).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`IBaseWindowModel` does *not* inherit `IBasePropertyChanged`**: It directly implements `INotifyPropertyChanged`. This is inconsistent with `IBaseViewModel` (which inherits `IBasePropertyChanged`). Developers may mistakenly assume both share the same base contract.
|
||||
- **`OnPropertyChanged` signature lacks default parameter**: The interface defines `void OnPropertyChanged(string propertyName);` without a default value (commented-out alternatives exist in source but are not part of the contract). Implementers *must* pass a non-null property name (or risk silent failures).
|
||||
- **`IsDirty` is read-only**: Its value must be computed internally (e.g., via `SetProperty` logic or manual tracking). No setter is exposed, so external state changes (e.g., after save) require updating via internal logic.
|
||||
- **`Initialize(object parameter, object model)` is `IBaseViewModel`-only**: `IBaseWindowModel` lacks this overload. Using it in a Window-level ViewModel may cause ambiguity or require custom implementation.
|
||||
- **No default implementations**: These are *interfaces only*. Concrete behavior (e.g., `SetProperty`, `IsDirty` tracking) must be provided by base classes or implementations (not documented here).
|
||||
- **Namespace quirk**: All interfaces use `DTS.Common.Base` despite being in `DTS.CommonCore` paths. This may cause confusion if namespace resolution is expected to match folder structure.
|
||||
|
||||
*None identified from source alone.*
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Base/Model/BaseModel.cs
|
||||
generated_at: "2026-04-16T02:51:14.177689+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "ed3fc24e01d7b3b1"
|
||||
---
|
||||
|
||||
# Model
|
||||
|
||||
### 1. **Purpose**
|
||||
`BaseModel<TModel>` is an abstract base class intended to provide foundational functionality for model objects within the `DTS.Common.Base` namespace. It encapsulates common state—specifically, a `Model` property of generic type `TModel` and an `IsSaved` flag indicating persistence status—and inherits from `BasePropertyChanged`, presumably to support property change notifications (e.g., for UI binding). Its role is to standardize model representation and lifecycle tracking across derived model types in the codebase.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
- **`public TModel Model { get; set; }`**
|
||||
Gets or sets the underlying model object. The type `TModel` is constrained to be a reference type (`class`). This property holds the actual data payload for the model instance.
|
||||
|
||||
- **`public bool IsSaved { get; private set; }`**
|
||||
Gets a read-only flag indicating whether the model has been persisted (e.g., saved to a database or backend). The setter is `private`, meaning only code within `BaseModel<TModel>` (e.g., derived classes or internal logic) can update this state.
|
||||
|
||||
- **`public BaseModel()`**
|
||||
Public parameterless constructor for the abstract base class. Allows instantiation of concrete derived types. (Note: The class is `abstract`, so direct instantiation is not possible—this constructor is only invoked via derived classes.)
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
- `TModel` must be a reference type (enforced by `where TModel : class`).
|
||||
- `IsSaved` is initialized to `false` by default (C# default for `bool`) and can only be modified internally (via `private set`). External code can read but not directly set this flag.
|
||||
- The class inherits from `BasePropertyChanged`, implying that property change notifications (e.g., `INotifyPropertyChanged`) are expected to be supported, though the specific implementation details are not visible in this file.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Depends on**:
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class; assumed to implement `INotifyPropertyChanged` or similar).
|
||||
- `DTS.Common.Base.IBaseModel` (interface implemented explicitly via `IBaseModel`).
|
||||
- The `TModel` type parameter is constrained to `class`, but no other constraints are specified.
|
||||
|
||||
- **Depended on by**:
|
||||
- Concrete model classes in the codebase that derive from `BaseModel<TModel>` (e.g., `public class CustomerModel : BaseModel<Customer>`).
|
||||
- Likely used by UI layers or services that interact with model instances via `IBaseModel` (e.g., for polymorphic handling of model state).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **`IsSaved` is not automatically managed**: The flag is exposed but has no built-in logic to update it (e.g., on save operations). Consumers must manually set `IsSaved = true` (e.g., in derived classes or service layers), which could lead to inconsistencies if overlooked.
|
||||
- **No validation or cloning support**: The class provides no hooks for validation, deep copying, or immutability—these must be implemented in derived classes if needed.
|
||||
- **`Model` property is nullable**: Since `TModel` is unconstrained beyond `class`, `Model` may be `null`. Consumers must handle null cases explicitly.
|
||||
- **No documentation for `IBaseModel` interface**: Its contract (e.g., members like `IsSaved`) is not visible here, so behavior relies on external definitions.
|
||||
- **`BasePropertyChanged` is not defined here**: Its behavior (e.g., how property change notifications are raised) is unknown from this file alone.
|
||||
|
||||
*None identified from source alone.*
|
||||
79
enriched-qwen3-coder-next/Common/DTS.CommonCore/Base/View.md
Normal file
79
enriched-qwen3-coder-next/Common/DTS.CommonCore/Base/View.md
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Base/View/BaseWindow.cs
|
||||
- Common/DTS.CommonCore/Base/View/BaseView.cs
|
||||
generated_at: "2026-04-16T02:51:29.370197+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e8beceb1bd7a7dfb"
|
||||
---
|
||||
|
||||
# View
|
||||
|
||||
## Documentation: `DTS.Common.Base` View Base Classes
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
This module provides foundational WPF view base classes (`BaseWindow` and `BaseView`) that standardize behavior for UI components in the application. These classes abstract common concerns—specifically, determining whether the underlying data model has unsaved changes (`IsDirty`) and retrieving a display-friendly header string (`HeaderInfo`) for tabbed interfaces—by delegating to interfaces implemented by the `DataContext`. They serve as reusable base classes to enforce consistency across views and reduce boilerplate in derived window and user control implementations.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `BaseWindow`
|
||||
- **Namespace**: `DTS.Common.Base`
|
||||
- **Inherits**: `System.Windows.Window`, implements `IBaseWindow` (interface not shown in source; assumed to declare `IsDirty` and `HeaderInfo` members).
|
||||
|
||||
- **`public bool IsDirty { get; }`**
|
||||
Returns `true` if the `DataContext` implements `IBaseWindowModel` *and* its `IsDirty` property is `true`; otherwise `false`. Returns `false` if `DataContext` is `null` or does not implement `IBaseWindowModel`.
|
||||
|
||||
- **`public string HeaderInfo { get; }`**
|
||||
Returns the `HeaderInfo` string from the `DataContext` *if* it implements `IHeaderInfoProvider<string>`; otherwise returns `string.Empty`.
|
||||
|
||||
#### `BaseView`
|
||||
- **Namespace**: `DTS.Common.Base`
|
||||
- **Inherits**: `System.Windows.Controls.UserControl`, implements `IBaseView` (interface not shown in source; assumed to declare `IsDirty` and `HeaderInfo` members).
|
||||
|
||||
- **`public bool IsDirty { get; }`**
|
||||
Returns `true` if the `DataContext` implements `IBaseViewModel` *and* its `IsDirty` property is `true`; otherwise `false`. Returns `false` if `DataContext` is `null` or does not implement `IBaseViewModel`.
|
||||
|
||||
- **`public string HeaderInfo { get; }`**
|
||||
Returns the `HeaderInfo` string from the `DataContext` *if* it implements `IHeaderInfoProvider<string>`; otherwise returns `string.Empty`.
|
||||
|
||||
> **Note**: Both classes use identical logic for `HeaderInfo`, but differ in the interface they check for `IsDirty`: `IBaseWindowModel` (for `BaseWindow`) vs. `IBaseViewModel` (for `BaseView`). The interfaces `IBaseWindowModel` and `IBaseViewModel` are not defined in the provided source.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- `IsDirty` **always** returns `false` if `DataContext` is `null`.
|
||||
- `IsDirty` **only** reads from the `DataContext`; it does not modify state.
|
||||
- `HeaderInfo` **always** returns a non-null string (`string.Empty` if no provider is available).
|
||||
- Both classes assume `DataContext` is set *before* `IsDirty` or `HeaderInfo` is accessed (though no explicit ordering requirement is enforced).
|
||||
- The `IsDirty` logic is **passive**: it reflects the state of the `DataContext` but does not trigger updates or subscriptions.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### External Dependencies (from source):
|
||||
- `System.Windows` (WPF framework) — required for `Window` and `UserControl` base types.
|
||||
- Interfaces `IBaseWindowModel`, `IBaseViewModel`, and `IHeaderInfoProvider<string>` — referenced but not defined in the provided source. Their definitions must exist elsewhere in the codebase (likely in `DTS.Common.Base` or a related namespace).
|
||||
|
||||
#### Internal Dependencies:
|
||||
- **Consumers**: Any WPF window or user control inheriting from `BaseWindow` or `BaseView` (e.g., custom `MainWindow : BaseWindow`).
|
||||
- **Required by `DataContext`**:
|
||||
- For `BaseWindow`: `DataContext` must implement `IBaseWindowModel` to participate in `IsDirty` reporting.
|
||||
- For `BaseView`: `DataContext` must implement `IBaseViewModel` to participate in `IsDirty` reporting.
|
||||
- For *both*: `DataContext` must implement `IHeaderInfoProvider<string>` to provide a non-empty `HeaderInfo`.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **Interface mismatch risk**: `BaseWindow` checks for `IBaseWindowModel`, while `BaseView` checks for `IBaseViewModel`. If a shared model implements both (or neither), behavior may be inconsistent or misleading.
|
||||
- **No fallback or logging**: If `DataContext` is misconfigured (e.g., implements `IHeaderInfoProvider<string>` but returns `null`), `HeaderInfo` will still return `string.Empty`—no warning or exception occurs.
|
||||
- **No change notification**: `IsDirty` is a synchronous read-only property. It does not raise `INotifyPropertyChanged` events, so UI bindings to `IsDirty` (e.g., for tab indicators) may not update automatically when the underlying model changes. Consumers must ensure `DataContext` raises `PropertyChanged` for `IsDirty` *and* re-evaluates the property (e.g., via `OnPropertyChanged(nameof(IsDirty))` in the view model).
|
||||
- **Ambiguous naming**: The XML comments refer to “IBaseWindowModel” and “IBaseViewModel” but do not clarify their relationship or whether they overlap. Without seeing their definitions, it is unclear if a single `DataContext` could implement both.
|
||||
- **No null-safety for `HeaderInfo`**: If `IHeaderInfoProvider<string>.HeaderInfo` returns `null`, the property will return `null` (not `string.Empty`). The code only guards against missing interface implementation, not interface contract violations.
|
||||
|
||||
> **None identified from source alone** for additional issues beyond those inferred from the logic and naming patterns.
|
||||
@@ -0,0 +1,182 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Base/ViewModel/ViewModelBase.cs
|
||||
- Common/DTS.CommonCore/Base/ViewModel/BaseViewModel.cs
|
||||
generated_at: "2026-04-16T02:51:04.199849+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e292dc2f8a859c0e"
|
||||
---
|
||||
|
||||
# ViewModel
|
||||
|
||||
## Documentation: ViewModel Base Classes (`DTS.Common.Base`)
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides two foundational abstract base classes for implementing ViewModels in the Prism-based WPF UI layer: `ViewModelBase<T>` (a minimal, model-centric base) and `BaseViewModel<TModel>` (a richer, infrastructure-aware base integrating Prism, Unity DI, and region management). `ViewModelBase<T>` serves as a low-level abstraction for custom ViewModel implementations requiring explicit control over model lifecycle, async initialization, and property change notifications. `BaseViewModel<TModel>` extends this with Prism-specific services (event aggregator, region manager, container), built-in command infrastructure (`CloseCommand`, `ConfirmationRequest`), and standardized initialization/cleanup hooks—aiming to reduce boilerplate in typical ViewModels while enforcing consistent lifecycle management and status reporting.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `ViewModelBase<T>` (in `ViewModelBase.cs`)
|
||||
|
||||
- **`public object Model { get; set; }`**
|
||||
Holds the underlying model object. Stored as `object`; cast to `T` internally.
|
||||
|
||||
- **`public bool IsBusy { get; protected set; }`**
|
||||
Read-only public property indicating whether an asynchronous operation is in progress. Protected setter allows derived classes to update it.
|
||||
|
||||
- **`public virtual bool IsDirty { get; protected set; }`**
|
||||
Read-only public property indicating whether the `Model` has unsaved changes. Virtual to allow overriding.
|
||||
|
||||
- **`public virtual event EventHandler<ErrorEventArgs> ErrorOccurred;`**
|
||||
Event raised when an error occurs during processing.
|
||||
|
||||
- **`public virtual event PropertyChangedEventHandler PropertyChanged;`**
|
||||
Standard `INotifyPropertyChanged` event for property change notifications.
|
||||
|
||||
- **`protected abstract Task<T> InitializeAsync();`**
|
||||
Override to implement async model initialization. The returned `Task<T>` result is used to populate the `Model` property.
|
||||
|
||||
- **`protected abstract void DoRefresh(Func<T> factoryMethod);`**
|
||||
Override to implement model refresh logic using a static factory method.
|
||||
|
||||
- **`protected abstract void OnError(Exception error);`**
|
||||
Override to raise the `ErrorOccurred` event.
|
||||
|
||||
- **`protected abstract void OnModelChanged(T oldValue, T newValue);`**
|
||||
Override to handle model replacement (e.g., unhooking/hooking event handlers on the old/new model).
|
||||
|
||||
- **`protected abstract void OnPropertyChanged(string propertyName);`**
|
||||
Override to raise the `PropertyChanged` event.
|
||||
|
||||
> **Note**: `ViewModelBase<T>` implements `INotifyPropertyChanged` and `IViewModel` (interface not shown), and inherits from `DependencyObject`.
|
||||
|
||||
---
|
||||
|
||||
#### `BaseViewModel<TModel>` (in `BaseViewModel.cs`)
|
||||
|
||||
- **`protected IEventAggregator Aggregator { get; }`**
|
||||
Prism event aggregator for pub/sub messaging.
|
||||
|
||||
- **`protected IUnityContainer Container { get; }`**
|
||||
Unity DI container for service resolution.
|
||||
|
||||
- **`protected IRegionManager _regionManager { get; }`**
|
||||
Prism region manager for view navigation/region population.
|
||||
|
||||
- **`public TModel Model { get; set; }`**
|
||||
Strongly-typed model object (contrasted with `ViewModelBase<T>.Model` which is `object`).
|
||||
|
||||
- **`public InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
|
||||
Prism `InteractionRequest` for displaying confirmation dialogs.
|
||||
|
||||
- **`public DelegateCommand<object> CloseCommand { get; }`**
|
||||
Command to close the view/viewmodel; executes `CloseMethod`, which in turn calls `CleanupAtClose()` → `Cleanup()`.
|
||||
|
||||
- **`protected virtual void CloseMethod(object parameter)`**
|
||||
Default implementation invokes `CleanupAtClose()`.
|
||||
|
||||
- **`public virtual void Activated()`**
|
||||
Hook called after viewmodel activation (e.g., by Prism region navigation). Default is no-op.
|
||||
|
||||
- **`public virtual void Initialize()`**
|
||||
Publishes a `ShowStatus` event with `StatusState.Busy` and `"Loading"` message via `Aggregator`.
|
||||
|
||||
- **`public virtual void Initialize(object parameter)`**
|
||||
Same as above; accepts initialization parameter (unused in current implementation).
|
||||
|
||||
- **`public virtual void Initialize(object parameter, object model)`**
|
||||
Placeholder with no implementation.
|
||||
|
||||
- **`public virtual async Task InitializeAsync()`**
|
||||
Async version of `Initialize()`, marshals `ShowStatus` publish to UI thread via `Dispatcher.CurrentDispatcher.InvokeAsync`.
|
||||
|
||||
- **`public virtual async Task InitializeAsync(object parameter)`**
|
||||
Async version of `Initialize(object)`.
|
||||
|
||||
- **`public new event PropertyChangedEventHandler PropertyChanged;`**
|
||||
Shadows base `PropertyChanged` event (likely from `BasePropertyChanged`, not shown).
|
||||
|
||||
- **`public bool IsMenuIncluded { get; set; }`**
|
||||
Flag indicating whether the view includes a menu.
|
||||
|
||||
- **`public bool IsNavigationIncluded { get; set; }`**
|
||||
Flag indicating whether the view includes navigation controls.
|
||||
|
||||
- **`public int Percentage { get; set; }`**
|
||||
Status progress percentage (e.g., for loading bars).
|
||||
|
||||
- **`public string IsBusyMessage { get; set; }`**
|
||||
Custom busy message to display.
|
||||
|
||||
- **`public bool IsBusy { get; set; }`**
|
||||
Busy state flag (redundant with `ViewModelBase<T>.IsBusy`; no synchronization between the two).
|
||||
|
||||
- **`public bool IsDirty { get; set; }`**
|
||||
Dirty state flag (redundant with `ViewModelBase<T>.IsDirty`; no synchronization).
|
||||
|
||||
- **`public virtual void Cleanup()`**
|
||||
Sets `Model` to `default(TModel)`.
|
||||
|
||||
- **`public Task CleanupAsync()`**
|
||||
**Throws `NotImplementedException`** — not implemented.
|
||||
|
||||
> **Note**: `BaseViewModel<TModel>` inherits from `BasePropertyChanged` (not shown), implements `IBaseViewModel` (not shown), and requires `TModel : class`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **`ViewModelBase<T>`**:
|
||||
- `InitializeAsync()` must return a `Task<T>` whose result is assigned to `Model`.
|
||||
- `OnModelChanged` must be called whenever `Model` changes (implementation responsibility of derived class).
|
||||
- `OnPropertyChanged` must be called for all property changes requiring UI updates.
|
||||
- `OnError` must be called to raise `ErrorOccurred`.
|
||||
|
||||
- **`BaseViewModel<TModel>`**:
|
||||
- `Initialize()`/`InitializeAsync()` *must* publish a `ShowStatus` event with `StatusInfo.StatusState.Busy` and `"Loading"` message during initialization.
|
||||
- `CloseCommand` always triggers `Cleanup()` (via `CleanupAtClose()`).
|
||||
- `Cleanup()` sets `Model = default(TModel)`.
|
||||
- `IsBusy`, `IsDirty`, `Percentage`, `IsBusyMessage`, `IsMenuIncluded`, and `IsNavigationIncluded` are *not* synchronized with any internal state machine — their values are purely application-defined.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### `ViewModelBase<T>`
|
||||
- **System namespaces**: `System`, `System.ComponentModel`, `System.Diagnostics`, `System.IO`, `System.Threading.Tasks`, `System.Windows`.
|
||||
- **Implements**: `INotifyPropertyChanged`, `IViewModel` (external interface).
|
||||
- **Inherits**: `DependencyObject`.
|
||||
- **Used by**: Any ViewModel requiring low-level control over model lifecycle and notifications.
|
||||
|
||||
#### `BaseViewModel<TModel>`
|
||||
- **Prism namespaces**: `Microsoft.Practices.Prism.Events`, `Microsoft.Practices.Prism.Commands`, `Microsoft.Practices.Prism.Regions`, `Microsoft.Practices.Prism.Interactivity.InteractionRequest`.
|
||||
- **Unity DI**: `Microsoft.Practices.Unity`.
|
||||
- **Internal namespaces**: `DTS.Common.Events` (for `ShowStatus`, `StatusInfo`, `Strings`).
|
||||
- **Inherits**: `BasePropertyChanged` (unseen, assumed to provide `INotifyPropertyChanged`).
|
||||
- **Implements**: `IBaseViewModel` (external interface).
|
||||
- **Depends on**:
|
||||
- `IRegionManager`, `IEventAggregator`, `IUnityContainer` (injected via constructor).
|
||||
- `Strings.Strings.Loading` (string resource).
|
||||
- `Dispatcher.CurrentDispatcher` (for async marshaling).
|
||||
- **Used by**: Most ViewModels in the application requiring Prism integration.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`BaseViewModel<TModel>.CleanupAsync()` is unimplemented** — throws `NotImplementedException`. Do not call this method.
|
||||
- **Redundant state flags**: Both `ViewModelBase<T>` and `BaseViewModel<TModel>` define `IsBusy` and `IsDirty`. There is *no synchronization* between them. If a class inherits from both (or uses both), these flags may diverge.
|
||||
- **`Model` type mismatch**: `ViewModelBase<T>.Model` is `object`, while `BaseViewModel<TModel>.Model` is strongly-typed `TModel`. Mixing these bases may lead to casting issues.
|
||||
- **`Initialize(object parameter, object model)` is a no-op** — despite accepting parameters, it does nothing. Initialization logic must be implemented in other overloads.
|
||||
- **`BaseViewModel` uses `new event PropertyChangedEventHandler`** — this shadows any base `PropertyChanged` (e.g., from `BasePropertyChanged`), which may cause confusion if event handlers are attached to the wrong reference.
|
||||
- **No automatic `IsBusy`/`IsDirty` management**: Derived classes must manually update `IsBusy`/`IsDirty` (in `ViewModelBase<T>`) or rely on application logic (in `BaseViewModel<TModel>`).
|
||||
- **`DoRefresh`’s contract is underspecified**: The source does not clarify how/when `DoRefresh` should be called or how it interacts with `InitializeAsync`.
|
||||
- **`Strings.Strings.Loading` is referenced but not defined here** — assumes a `Strings` resource class exists in `DTS.Common` with a `Loading` property.
|
||||
|
||||
> **None identified from source alone** for `ViewModelBase<T>` beyond its minimal design. For `BaseViewModel<TModel>`, the above are the primary concerns.
|
||||
Reference in New Issue
Block a user