using System; using System.Collections.Generic; using System.ComponentModel; namespace DynamicDescriptors; /// /// A runtime-customizable implementation of . /// public sealed class DynamicPropertyDescriptor : PropertyDescriptor { /// /// The on which this is based. /// private readonly PropertyDescriptor _descriptor; /// /// A dictionary mapping editor base types to editor instances. /// private readonly IDictionary _editorDictionary; /// /// Gets or sets a value indicating whether the dynamic property descriptor is active. /// If not, it won't be returned by the /// or methods. /// private bool _active; /// /// If this value is not null, it will be returned by the Category property; /// otherwise, the base descriptor's Category property will be returned. /// private string _categoryOverride; /// /// If this value is not null, it will be returned by the Converter property; /// otherwise, the base descriptor's Converter property will be returned. /// private TypeConverter _converterOverride; /// /// If this value is not null, it will be returned by the Description property; /// otherwise, the base descriptor's Description property will be returned. /// private string _descriptionOverride; /// /// If this value is not null, it will be returned by the DisplayName property; /// otherwise, the base descriptor's DisplayName property will be returned. /// private string _displayNameOverride; /// /// If this value is not null, it will be returned by the IsReadOnly property; /// otherwise, the base descriptor's IsReadOnly property will be returned. /// private bool? _isReadOnlyOverride; /// /// The order in which this property will be retrieved from its type descriptor. /// private int? _propertyOrder; /// /// Initializes a new instance of the class. /// /// /// The on which this will be based. /// public DynamicPropertyDescriptor(PropertyDescriptor descriptor) : base(Preconditions.CheckNotNull(descriptor, nameof(descriptor))) { _descriptor = descriptor; _editorDictionary = new Dictionary(); _active = true; } /// /// Gets or sets a value indicating whether the dynamic property descriptor is active. /// If not, it won't be returned by the /// or methods. /// public bool Active { get => _active; set => _active = value; } /// /// Returns a value indicating whether resetting an object changes its value. /// /// The component to test for reset capability. /// true if resetting the component changes its value; otherwise, false. public override bool CanResetValue(object component) { return _descriptor.CanResetValue(component); } /// /// Gets the name of the category to which the member belongs, /// as specified in the . /// public override string Category => _categoryOverride ?? _descriptor.Category; /// /// Gets the type of the component this property is bound to. /// public override Type ComponentType => _descriptor.ComponentType; /// /// Gets the type converter for this property. /// public override TypeConverter Converter => _converterOverride ?? _descriptor.Converter; /// /// Gets the description of the member, /// as specified in the . /// public override string Description => _descriptionOverride ?? _descriptor.Description; /// /// Gets the name that can be displayed in a window, such as a Properties window. /// public override string DisplayName => _displayNameOverride ?? _descriptor.DisplayName; /// /// Gets an editor of the specified type. /// /// /// The base type of editor, which is used to differentiate between multiple /// editors that a property supports. /// /// /// An instance of the requested editor type, or null if an editor cannot be found. /// public override object GetEditor(Type editorBaseType) { if (editorBaseType != null) { if (_editorDictionary.TryGetValue(editorBaseType, out var editor)) { return editor; } } return _descriptor.GetEditor(editorBaseType); } /// /// Returns the current value of the property on a component. /// /// /// The component with the property for which to retrieve the value. /// /// The value of a property for a given component. public override object GetValue(object component) { return _descriptor.GetValue(component); } /// /// Gets a value indicating whether this property is read-only. /// public override bool IsReadOnly => _isReadOnlyOverride ?? _descriptor.IsReadOnly; /// /// Gets the order in which this property will be retrieved from its type descriptor. /// public int? PropertyOrder => _propertyOrder; /// /// Gets the type of the property. /// public override Type PropertyType => _descriptor.PropertyType; /// /// Resets the value for this property of the component to the default value. /// /// /// The component with the property value that is to be reset to the default value. /// public override void ResetValue(object component) { _descriptor.ResetValue(component); OnValueChanged(component, EventArgs.Empty); } /// /// Sets the value of the component to a different value. /// /// /// The component with the property value that is to be set. /// /// /// The new value. /// public override void SetValue(object component, object value) { _descriptor.SetValue(component, value); OnValueChanged(component, EventArgs.Empty); } /// /// Determines a value indicating whether the value of this property needs to be persisted. /// /// /// The component with the property to be examined for persistence. /// /// true if the property should be persisted; otherwise, false. public override bool ShouldSerializeValue(object component) { return _descriptor.ShouldSerializeValue(component); } #region Fluent interface /// /// Sets value that determines whether the dynamic property descriptor is active. /// /// /// The value that determines whether the dynamic property descriptor is active. /// /// This instance. public DynamicPropertyDescriptor SetActive(bool active) { _active = active; return this; } /// /// Sets the override for the property. /// /// The new value for the property. /// This instance. public DynamicPropertyDescriptor SetCategory(string category) { _categoryOverride = category; return this; } /// /// Sets the override for the property. /// /// The new value for the property. /// This instance. public DynamicPropertyDescriptor SetConverter(TypeConverter converter) { _converterOverride = converter; return this; } /// /// Sets the override for the property. /// /// The new value for the property. /// This instance. public DynamicPropertyDescriptor SetDescription(string description) { _descriptionOverride = description; return this; } /// /// Sets the override for the property. /// /// The new value for the property. /// This instance. public DynamicPropertyDescriptor SetDisplayName(string displayName) { _displayNameOverride = displayName; return this; } /// /// Sets the editor for this type. /// /// /// The base type of editor, which is used to differentiate between multiple editors /// that a property supports. /// /// /// An instance of the requested editor type. /// /// This instance. public DynamicPropertyDescriptor SetEditor(Type editorBaseType, object editor) { if (editorBaseType != null) { if (_editorDictionary.ContainsKey(editorBaseType)) { if (editor == null) { _editorDictionary.Remove(editorBaseType); } else { _editorDictionary[editorBaseType] = editor; } } else { if (editor != null) { _editorDictionary.Add(editorBaseType, editor); } } } return this; } /// /// Sets the order in which this property will be retrieved from its type descriptor. /// /// The order in which this property will be retrieved. /// This instance. public DynamicPropertyDescriptor SetPropertyOrder(int? propertyOrder) { _propertyOrder = propertyOrder; return this; } /// /// Sets the override for the property. /// /// The new value for the property. /// This instance. public DynamicPropertyDescriptor SetReadOnly(bool? readOnly) { _isReadOnlyOverride = readOnly; return this; } #endregion }