File: System\ComponentModel\ExtendedPropertyDescriptor.cs
Web Access
Project: src\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj (System.ComponentModel.TypeConverter)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
 
namespace System.ComponentModel
{
    /// <summary>
    /// This class wraps an PropertyDescriptor with something that looks like a property. It
    /// allows you to treat extended properties the same as regular properties.
    /// </summary>
    internal sealed class ExtendedPropertyDescriptor : PropertyDescriptor
    {
        private readonly ReflectPropertyDescriptor _extenderInfo;       // the extender property
        private readonly IExtenderProvider _provider;           // the object providing it
 
        /// <summary>
        /// Creates a new extended property info. Callers can then treat this as
        /// a standard property.
        /// </summary>
        public ExtendedPropertyDescriptor(ReflectPropertyDescriptor extenderInfo, Type? receiverType, IExtenderProvider provider, Attribute[]? attributes)
            : base(extenderInfo, attributes)
        {
            Debug.Assert(extenderInfo != null, "ExtendedPropertyDescriptor must have extenderInfo");
            Debug.Assert(provider != null, "ExtendedPropertyDescriptor must have provider");
 
            List<Attribute> attrList = new List<Attribute>(AttributeArray!)
            {
                ExtenderProvidedPropertyAttribute.Create(extenderInfo, receiverType, provider)
            };
            if (extenderInfo.IsReadOnly)
            {
                attrList.Add(ReadOnlyAttribute.Yes);
            }
 
            Attribute[] temp = new Attribute[attrList.Count];
            attrList.CopyTo(temp, 0);
            AttributeArray = temp;
 
            _extenderInfo = extenderInfo;
            _provider = provider;
        }
 
        public ExtendedPropertyDescriptor(PropertyDescriptor extender, Attribute[] attributes) : base(extender, attributes)
        {
            Debug.Assert(extender != null, "The original PropertyDescriptor must be non-null");
 
            ExtenderProvidedPropertyAttribute? attr = extender.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
 
            Debug.Assert(attr != null, "The original PropertyDescriptor does not have an ExtenderProvidedPropertyAttribute");
 
 
            ReflectPropertyDescriptor? reflectDesc = attr.ExtenderProperty as ReflectPropertyDescriptor;
 
            Debug.Assert(reflectDesc != null, "The original PropertyDescriptor has an invalid ExtenderProperty");
 
            _extenderInfo = reflectDesc;
            _provider = attr.Provider!;
        }
 
        /// <summary>
        /// Determines if the component will allow its value to be reset.
        /// </summary>
        public override bool CanResetValue(object comp)
        {
            return _extenderInfo.ExtenderCanResetValue(_provider, comp);
        }
 
        /// <summary>
        /// Retrieves the type of the component this PropertyDescriptor is bound to.
        /// </summary>
        public override Type ComponentType => _extenderInfo.ComponentType;
 
        /// <summary>
        /// Determines if the property can be written to.
        /// </summary>
        public override bool IsReadOnly => Attributes[typeof(ReadOnlyAttribute)]!.Equals(ReadOnlyAttribute.Yes);
 
        /// <summary>
        /// Retrieves the data type of the property.
        /// </summary>
        public override Type PropertyType => _extenderInfo.ExtenderGetType();
 
        /// <summary>
        /// Retrieves the display name of the property. This is the name that will
        /// be displayed in a properties window. This will be the same as the property
        /// name for most properties.
        /// </summary>
        public override string DisplayName
        {
            get
            {
                string name = base.DisplayName;
 
                if (!(Attributes[typeof(DisplayNameAttribute)] is DisplayNameAttribute displayNameAttr) || displayNameAttr.IsDefaultAttribute())
                {
                    ISite? site = GetSite(_provider);
                    string? providerName = site?.Name;
                    if (providerName != null && providerName.Length > 0)
                    {
                        name = SR.Format(SR.UsingResourceKeys() ? "{0} on {1}" : SR.MetaExtenderName, name, providerName);
                    }
                }
                return name;
            }
        }
 
        /// <summary>
        /// Retrieves the value of the property for the given component. This will
        /// throw an exception if the component does not have this property.
        /// </summary>
        public override object? GetValue(object? comp) => _extenderInfo.ExtenderGetValue(_provider, comp);
 
        /// <summary>
        /// Resets the value of this property on comp to the default value.
        /// </summary>
        public override void ResetValue(object comp) => _extenderInfo.ExtenderResetValue(_provider, comp, this);
 
        /// <summary>
        /// Sets the value of this property on the given component.
        /// </summary>
        public override void SetValue(object? component, object? value)
        {
            _extenderInfo.ExtenderSetValue(_provider, component, value, this);
        }
 
        /// <summary>
        /// Determines if this property should be persisted. A property is
        /// to be persisted if it is marked as persistable through a
        /// PersistableAttribute, and if the property contains something other
        /// than the default value. Note, however, that this method will
        /// return true for design time properties as well, so callers
        /// should also check to see if a property is design time only before
        /// persisting to runtime storage.
        /// </summary>
        public override bool ShouldSerializeValue(object comp)
        {
            return _extenderInfo.ExtenderShouldSerializeValue(_provider, comp);
        }
    }
}