12 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | ||||
|---|---|---|---|---|---|---|---|---|
|
2026-04-16T02:51:28.846308+00:00 | Qwen/Qwen3-Coder-Next-FP8 | 1 | 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)
Comparesstorageandvaluefor equality; if different, updatesstorage, invokesOnPropertyChanged, and returnstrue. Returnsfalseif values are equal. Used to implementINotifyPropertyChangedconcisely. -
virtual void OnPropertyChanged(string propertyName = null)
Raises thePropertyChangedevent with the given property name. IfpropertyNameisnull, raisesPropertyChangedEventArgs.Empty.
DisplayResourceAttribute
-
DisplayResourceAttribute(string resourceId)
Constructor. StoresresourceIdfor later lookup inStrings.Strings.ResourceManager. -
override string DisplayName
Returns the localized string fromStrings.Strings.ResourceManager.GetString(resourceId), or"##ResourceNotFound##" + resourceIdif not found.
DescriptionResourceAttribute
-
DescriptionResourceAttribute(string resourceId)
Constructor. StoresresourceIdfor later lookup inStrings.Strings.ResourceManager. -
override string Description
Returns the localized string fromStrings.Strings.ResourceManager.GetString(resourceId), or"##DescriptionNotFound##" + resourceIdif not found.
DynamicTypeDescriptor
-
DynamicTypeDescriptor(Type type)
Constructor. Initializes internal state by queryingTypeDescriptorfor the giventype. 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 namednamefrom the currentComponent, casting toT. ReturnsdefaultValueon failure or if property not found. -
void SetPropertyValue(string name, object value)
Sets the value of the property namednameon the currentComponent. 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 newDynamicPropertywith specified metadata. Overload omitsuiTypeEditor(defaults tonull). -
void AddProperty(PropertyDescriptor property)
Adds a pre-constructedPropertyDescriptor(e.g.,DynamicProperty) to thePropertiescollection. -
void RemoveProperty(string name)
Removes the property namednamefrom thePropertiescollection. -
DynamicTypeDescriptor FromComponent(object component)
Creates a newDynamicTypeDescriptorinstance bound tocomponent, copying original metadata and creatingDynamicPropertywrappers for each property. Requirescomponentto be assignable to the original_type. -
event PropertyChangedEventHandler PropertyChanged
ImplementsINotifyPropertyChanged. Raised internally viaOnValueChanged(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 byTypeDescriptor.GetProperties(type). -
object Component { get; }
The object instance whose properties are being described. Set only duringFromComponent. -
string ClassName { get; set; }/string ComponentName { get; set; }
Overridable display names for the type and component, respectively, used inICustomTypeDescriptor.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)
OverridesIsBrowsableandIsReadOnlybehavior. -
void RemoveAttributesOfType<T>()
Removes all attributes of typeT(or derived) from the internal_attributeslist. -
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_existingproperty, delegates to it; otherwise uses the internalValuefield. -
override void ResetValue(object component)
Resets value to default (if_existingexists, delegates; otherwise uses_defaultValueorValue). -
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_existingproperty.
3. Invariants
-
BasePropertyChanged.SetProperty- Only raises
PropertyChangedifstorageandvalueare not equal (viaEquals). storageis updated beforeOnPropertyChangedis called.
- Only raises
-
DynamicTypeDescriptorPropertiescollection excludes non-browsable properties at construction time (viaif (!property.IsBrowsable) continue;).FromComponentperforms a shallow copy of internal state (e.g.,_editors,_typeConverter), but creates newDynamicPropertyinstances per property.DynamicPropertyoverrides metadata only if explicitly set viaSet*methods; otherwise falls back to original or base behavior.DynamicTypeDescriptorimplementsICustomTypeDescriptorandINotifyPropertyChanged—consumers may rely on both interfaces.
-
DisplayResourceAttribute/DescriptionResourceAttributeDisplayName/Descriptionalways returns a non-null string: either the localized value or a fallback marker (##ResourceNotFound##/##DescriptionNotFound##) concatenated with theresourceId.- Resource lookup uses
Strings.Strings.ResourceManager.GetString(resourceId)—no automatic suffixing (e.g.,"PropertyName_Description"must be the exactresourceIdpassed to the constructor).
4. Dependencies
-
Internal Dependencies
System.ComponentModel(INotifyPropertyChanged,PropertyChangedEventHandler,Attribute,PropertyDescriptor, etc.).Strings.Strings.ResourceManager(fromDTS.Commonresources) forDisplayResourceAttributeandDescriptionResourceAttribute.System.Drawing.Design(UITypeEditor,EditorAttribute) for editor support inDynamicTypeDescriptor.
-
External Dependencies
DynamicTypeDescriptoris used by UI components (e.g.,PropertyGrid) that rely onICustomTypeDescriptor.BasePropertyChangedis intended for use by view models or entities requiringINotifyPropertyChanged.DisplayResourceAttribute/DescriptionResourceAttributeare 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.
- Likely consumed by UI layers (e.g., WinForms
5. Gotchas
-
DynamicTypeDescriptordoes not automatically propagate changes to the underlyingComponentwhen usingDynamicPropertywith no_existingproperty.SetValue/ResetValueonly update the internalValuefield of theDynamicProperty. To bind to real properties, useFromComponentto wrap an existing property descriptor. -
DynamicProperty.Attributesis a snapshot of_attributesat construction time unless modified viaRemoveAttributesOfType<T>orSet*methods. Direct mutation of_attributesis not exposed. -
DisplayResourceAttributeandDescriptionResourceAttributedo 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.SetPropertyusesEqualsfor comparison, which may be unsafe for mutable reference types (e.g., collections). Consider usingEqualityComparer<T>.Defaultor custom comparison if needed. -
DynamicTypeDescriptorfilters properties byIsBrowsableat construction time, so non-browsable properties (e.g.,DesignerSerializationVisibility.Hidden) are permanently excluded fromProperties. UseOriginalPropertiesto inspect all properties. -
DynamicTypeDescriptor.FromComponentrequirescomponent.GetType()to be assignable to_type. Passing a derived type may throwArgumentException. -
DynamicProperty’sShouldSerializeValuealways returnsfalseunless wrapping an_existingproperty—this may interfere with serialization logic expectingShouldSerialize*semantics. -
No thread-safety guarantees are documented or implied for
DynamicTypeDescriptororBasePropertyChanged. Concurrent access toPropertiesorPropertyChangedevents may require external synchronization. -
Strings.Strings.ResourceManagermust be initialized beforeDisplayResourceAttribute/DescriptionResourceAttributeare instantiated, orGetStringwill returnnull. 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.