/// <summary>
        /// Will reset the default value for this property on the component. If
        /// there was a default value passed in as a DefaultValueAttribute, that
        /// value will be set as the value of the property on the component. If
        /// there was no default value passed in, a ResetXXX method will be looked
        /// for. If one is found, it will be invoked. If one is not found, this
        /// is a nop.
        /// </summary>
        public override void ResetValue(object component)
        {
            object invokee = GetInvocationTarget(_componentClass, component);

            if (DefaultValue != s_noValue)
            {
                SetValue(component, DefaultValue);
            }
            else if (AmbientValue != s_noValue)
            {
                SetValue(component, AmbientValue);
            }
            else if (ResetMethodValue != null)
            {
                ISite site = GetSite(component);
                IComponentChangeService changeService = null;
                object oldValue = null;
                object newValue;

                // Announce that we are about to change this component
                if (site != null)
                {
                    changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
                    Debug.Assert(!ComponentModelSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
                }

                // Make sure that it is ok to send the onchange events
                if (changeService != null)
                {
                    // invokee might be a type from mscorlib or system, GetMethodValue might return a NonPublic method
                    oldValue = GetMethodValue.Invoke(invokee, null);
                    try
                    {
                        changeService.OnComponentChanging(component, this);
                    }
                    catch (CheckoutException coEx)
                    {
                        if (coEx == CheckoutException.Canceled)
                        {
                            return;
                        }
                        throw;
                    }
                }

                if (ResetMethodValue != null)
                {
                    ResetMethodValue.Invoke(invokee, null);

                    // Now notify the change service that the change was successful.
                    if (changeService != null)
                    {
                        newValue = GetMethodValue.Invoke(invokee, null);
                        changeService.OnComponentChanged(component, this, oldValue, newValue);
                    }
                }
            }
        }
 internal object ExtenderGetValue(IExtenderProvider provider, object component)
 {
     if (provider != null)
     {
         provider = (IExtenderProvider)GetInvocationTarget(_componentClass, provider);
         return(GetMethodValue.Invoke(provider, new object[] { component }));
     }
     return(null);
 }
        /// <summary>
        /// Retrieves the current value of the property on component,
        /// invoking the getXXX method. An exception in the getXXX
        /// method will pass through.
        /// </summary>
        public override object GetValue(object component)
        {
            Debug.WriteLine($"[{Name}]: GetValue({component?.GetType().Name ?? "(null)"})");

            if (IsExtender)
            {
                Debug.WriteLine($"[{Name}]:   ---> returning: null");
                return(null);
            }

            Debug.Assert(component != null, "GetValue must be given a component");

            if (component != null)
            {
                component = GetInvocationTarget(_componentClass, component);


                try
                {
                    return(GetMethodValue.Invoke(component, null));
                }
                catch (Exception t)
                {
                    string     name = null;
                    IComponent comp = component as IComponent;
                    ISite      site = comp?.Site;
                    if (site?.Name != null)
                    {
                        name = site.Name;
                    }

                    if (name == null)
                    {
                        name = component.GetType().FullName;
                    }

                    if (t is TargetInvocationException)
                    {
                        t = t.InnerException;
                    }

                    string message = t.Message ?? t.GetType().Name;

                    throw new TargetInvocationException(SR.Format(SR.ErrorPropertyAccessorException, Name, name, message), t);
                }
            }
            Debug.WriteLine("[" + Name + "]:   ---> returning: null");
            return(null);
        }
        /// <summary>
        /// This will set value to be the new value of this property on the
        /// component by invoking the setXXX method on the component. If the
        /// value specified is invalid, the component should throw an exception
        /// which will be passed up. The component designer should design the
        /// property so that getXXX following a setXXX should return the value
        /// passed in if no exception was thrown in the setXXX call.
        /// </summary>
        public override void SetValue(object component, object value)
        {
            Debug.WriteLine($"[{Name}]: SetValue({component?.GetType().Name ?? "(null)"}, {value?.GetType().Name ?? "(null)"})");

            if (component != null)
            {
                ISite  site     = GetSite(component);
                object oldValue = null;

                object invokee = GetInvocationTarget(_componentClass, component);

                if (!IsReadOnly)
                {
                    IComponentChangeService changeService = null;

                    // Announce that we are about to change this component
                    if (site != null)
                    {
                        changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
                    }

                    // Make sure that it is ok to send the onchange events
                    if (changeService != null)
                    {
                        oldValue = GetMethodValue.Invoke(invokee, null);
                        try
                        {
                            changeService.OnComponentChanging(component, this);
                        }
                        catch (CheckoutException coEx)
                        {
                            if (coEx == CheckoutException.Canceled)
                            {
                                return;
                            }
                            throw;
                        }
                    }

                    try
                    {
                        try
                        {
                            SetMethodValue.Invoke(invokee, new object[] { value });
                            OnValueChanged(invokee, EventArgs.Empty);
                        }
                        catch (Exception t)
                        {
                            // Give ourselves a chance to unwind properly before rethrowing the exception.
                            //
                            value = oldValue;

                            // If there was a problem setting the controls property then we get:
                            // ArgumentException (from properties set method)
                            // ==> Becomes inner exception of TargetInvocationException
                            // ==> caught here

                            if (t is TargetInvocationException && t.InnerException != null)
                            {
                                // Propagate the original exception up
                                throw t.InnerException;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                    finally
                    {
                        // Now notify the change service that the change was successful.
                        changeService?.OnComponentChanged(component, this, oldValue, value);
                    }
                }
            }
        }
        /// <include file='doc\ReflectPropertyDescriptor.uex' path='docs/doc[@for="ReflectPropertyDescriptor.GetValue"]/*' />
        /// <devdoc>
        ///     Retrieves the current value of the property on component,
        ///     invoking the getXXX method.  An exception in the getXXX
        ///     method will pass through.
        /// </devdoc>
        public override object GetValue(object component)
        {
#if DEBUG
            if (PropDescUsageSwitch.TraceVerbose)
            {
                string compName = "(null)";
                if (component != null)
                {
                    compName = component.ToString();
                }

                Debug.WriteLine("[" + Name + "]: GetValue(" + compName + ")");
            }
#endif

            if (IsExtender)
            {
                Debug.WriteLineIf(PropDescUsageSwitch.TraceVerbose, "[" + Name + "]:   ---> returning: null");
                return(null);
            }

            Debug.Assert(component != null, "GetValue must be given a component");

            if (component != null)
            {
                component = GetInvokee(componentClass, component);


                try {
                    return(GetMethodValue.Invoke(component, null));
                }
                catch (Exception t) {
                    string name = null;
                    if (component is IComponent)
                    {
                        ISite site = ((IComponent)component).Site;
                        if (site != null && site.Name != null)
                        {
                            name = site.Name;
                        }
                    }

                    if (name == null)
                    {
                        name = component.GetType().FullName;
                    }

                    if (t is TargetInvocationException)
                    {
                        t = t.InnerException;
                    }

                    string message = t.Message;
                    if (message == null)
                    {
                        message = t.GetType().Name;
                    }

                    throw new TargetInvocationException(SR.GetString(SR.ErrorPropertyAccessorException, Name, name, message), t);
                }
            }
            Debug.WriteLineIf(PropDescUsageSwitch.TraceVerbose, "[" + Name + "]:   ---> returning: null");
            return(null);
        }
        /// <include file='doc\ReflectPropertyDescriptor.uex' path='docs/doc[@for="ReflectPropertyDescriptor.SetValue"]/*' />
        /// <devdoc>
        ///     This will set value to be the new value of this property on the
        ///     component by invoking the setXXX method on the component.  If the
        ///     value specified is invalid, the component should throw an exception
        ///     which will be passed up.  The component designer should design the
        ///     property so that getXXX following a setXXX should return the value
        ///     passed in if no exception was thrown in the setXXX call.
        /// </devdoc>
        public override void SetValue(object component, object value)
        {
#if DEBUG
            if (PropDescUsageSwitch.TraceVerbose)
            {
                string compName = "(null)";
                string valName  = "(null)";

                if (component != null)
                {
                    compName = component.ToString();
                }
                if (value != null)
                {
                    valName = value.ToString();
                }

                Debug.WriteLine("[" + Name + "]: SetValue(" + compName + ", " + valName + ")");
            }
#endif
            if (component != null)
            {
                ISite site = GetSite(component);
                IComponentChangeService changeService = null;
                object oldValue = null;

                object invokee = GetInvokee(componentClass, component);

                Debug.Assert(!IsReadOnly, "SetValue attempted on read-only property [" + Name + "]");
                if (!IsReadOnly)
                {
                    // Announce that we are about to change this component
                    //
                    if (site != null)
                    {
                        changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
                        Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
                    }


                    // Make sure that it is ok to send the onchange events
                    //
                    if (changeService != null)
                    {
                        oldValue = GetMethodValue.Invoke(invokee, null);
                        try {
                            changeService.OnComponentChanging(component, this);
                        }
                        catch (CheckoutException coEx) {
                            if (coEx == CheckoutException.Canceled)
                            {
                                return;
                            }
                            throw coEx;
                        }
                    }

                    try {
                        try {
                            SetMethodValue.Invoke(invokee, new object[] { value });
                            OnValueChanged(invokee, EventArgs.Empty);
                        }
                        catch (Exception t) {
                            // Give ourselves a chance to unwind properly before rethrowing the exception (bug# 20221).
                            //
                            value = oldValue;

                            // If there was a problem setting the controls property then we get:
                            // ArgumentException (from properties set method)
                            // ==> Becomes inner exception of TargetInvocationException
                            // ==> caught here

                            if (t is TargetInvocationException && t.InnerException != null)
                            {
                                // Propagate the original exception up
                                throw t.InnerException;
                            }
                            else
                            {
                                throw t;
                            }
                        }
                    }
                    finally {
                        // Now notify the change service that the change was successful.
                        //
                        if (changeService != null)
                        {
                            changeService.OnComponentChanged(component, this, oldValue, value);
                        }
                    }
                }
            }
        }