The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ ReflectPropertyDescriptor

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ReflectPropertyDescriptor.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. /*
  16. */
  17. namespace System.ComponentModel
  18. {
  19.     using Microsoft.Win32;
  20.     using System;
  21.     using System.Collections;
  22.     using System.Collections.Specialized;
  23.     using System.ComponentModel.Design;
  24.     using System.Diagnostics;
  25.     using System.Globalization;
  26.     using System.Reflection;
  27.     using System.Runtime.InteropServices;
  28.     using System.Runtime.Serialization.Formatters;
  29.     using System.Security;
  30.     using System.Security.Permissions;
  31.    
  32.     /// <internalonly/>
  33.     /// <devdoc>
  34.     /// <para>
  35.     /// ReflectPropertyDescriptor defines a property. Properties are the main way that a user can
  36.     /// set up the state of a component.
  37.     /// The ReflectPropertyDescriptor class takes a component class that the property lives on,
  38.     /// a property name, the type of the property, and various attributes for the
  39.     /// property.
  40.     /// For a property named XXX of type YYY, the associated component class is
  41.     /// required to implement two methods of the following
  42.     /// form:
  43.     /// </para>
  44.     /// <code>
  45.     /// public YYY GetXXX();
  46.     /// public void SetXXX(YYY value);
  47.     /// </code>
  48.     /// The component class can optionally implement two additional methods of
  49.     /// the following form:
  50.     /// <code>
  51.     /// public boolean ShouldSerializeXXX();
  52.     /// public void ResetXXX();
  53.     /// </code>
  54.     /// These methods deal with a property's default value. The ShouldSerializeXXX()
  55.     /// method returns true if the current value of the XXX property is different
  56.     /// than it's default value, so that it should be persisted out. The ResetXXX()
  57.     /// method resets the XXX property to its default value. If the ReflectPropertyDescriptor
  58.     /// includes the default value of the property (using the DefaultValueAttribute),
  59.     /// the ShouldSerializeXXX() and ResetXXX() methods are ignored.
  60.     /// If the ReflectPropertyDescriptor includes a reference to an editor
  61.     /// then that value editor will be used to
  62.     /// edit the property. Otherwise, a system-provided editor will be used.
  63.     /// Various attributes can be passed to the ReflectPropertyDescriptor, as are described in
  64.     /// Attribute.
  65.     /// ReflectPropertyDescriptors can be obtained by a user programmatically through the
  66.     /// ComponentManager.
  67.     /// </devdoc>
  68.     [HostProtection(SharedState = true)]
  69.     internal sealed class ReflectPropertyDescriptor : PropertyDescriptor
  70.     {
  71.        
  72.         private static readonly Type[] argsNone = new Type[0];
  73.         private static readonly object noValue = new object();
  74.        
  75.         private static TraceSwitch PropDescCreateSwitch = new TraceSwitch("PropDescCreate", "ReflectPropertyDescriptor: Dump errors when creating property info");
  76.         private static TraceSwitch PropDescUsageSwitch = new TraceSwitch("PropDescUsage", "ReflectPropertyDescriptor: Debug propertydescriptor usage");
  77.         private static TraceSwitch PropDescSwitch = new TraceSwitch("PropDesc", "ReflectPropertyDescriptor: Debug property descriptor");
  78.        
  79.         private static readonly int BitDefaultValueQueried = BitVector32.CreateMask();
  80.         private static readonly int BitGetQueried = BitVector32.CreateMask(BitDefaultValueQueried);
  81.         private static readonly int BitSetQueried = BitVector32.CreateMask(BitGetQueried);
  82.         private static readonly int BitShouldSerializeQueried = BitVector32.CreateMask(BitSetQueried);
  83.         private static readonly int BitResetQueried = BitVector32.CreateMask(BitShouldSerializeQueried);
  84.         private static readonly int BitChangedQueried = BitVector32.CreateMask(BitResetQueried);
  85.         private static readonly int BitIPropChangedQueried = BitVector32.CreateMask(BitChangedQueried);
  86.         private static readonly int BitReadOnlyChecked = BitVector32.CreateMask(BitIPropChangedQueried);
  87.         private static readonly int BitAmbientValueQueried = BitVector32.CreateMask(BitReadOnlyChecked);
  88.         private static readonly int BitSetOnDemand = BitVector32.CreateMask(BitAmbientValueQueried);
  89.        
  90.        
  91.         BitVector32 state = new BitVector32();
  92.         // Contains the state bits for this proeprty descriptor.
  93.         Type componentClass;
  94.         // used to determine if we should all on us or on the designer
  95.         Type type;
  96.         // the data type of the property
  97.         object defaultValue;
  98.         // the default value of the property (or noValue)
  99.         object ambientValue;
  100.         // the ambient value of the property (or noValue)
  101.         PropertyInfo propInfo;
  102.         // the property info
  103.         MethodInfo getMethod;
  104.         // the property get method
  105.         MethodInfo setMethod;
  106.         // the property set method
  107.         MethodInfo shouldSerializeMethod;
  108.         // the should serialize method
  109.         MethodInfo resetMethod;
  110.         // the reset property method
  111.         EventDescriptor realChangedEvent;
  112.         // <propertyname>Changed event handler on object
  113.         EventDescriptor realIPropChangedEvent;
  114.         // INotifyPropertyChanged.PropertyChanged event handler on object
  115.         Type receiverType;
  116.         // Only set if we are an extender
  117.         /// <devdoc>
  118.         /// The main constructor for ReflectPropertyDescriptors.
  119.         /// </devdoc>
  120.         public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Attribute[] attributes) : base(name, attributes)
  121.         {
  122.            
  123.             Debug.WriteLineIf(PropDescCreateSwitch.TraceVerbose, "Creating ReflectPropertyDescriptor for " + componentClass.FullName + "." + name);
  124.            
  125.             try {
  126.                 if (type == null) {
  127.                     Debug.WriteLineIf(PropDescCreateSwitch.TraceVerbose, "type == null, name == " + name);
  128.                     throw new ArgumentException(SR.GetString(SR.ErrorInvalidPropertyType, name));
  129.                 }
  130.                 if (componentClass == null) {
  131.                     Debug.WriteLineIf(PropDescCreateSwitch.TraceVerbose, "componentClass == null, name == " + name);
  132.                     throw new ArgumentException(SR.GetString(SR.InvalidNullArgument, "componentClass"));
  133.                 }
  134.                 this.type = type;
  135.                 this.componentClass = componentClass;
  136.             }
  137.             catch (Exception t) {
  138.                 Debug.Fail("Property '" + name + "' on component " + componentClass.FullName + " failed to init.");
  139.                 Debug.Fail(t.ToString());
  140.                 throw t;
  141.             }
  142.         }
  143.        
  144.         /// <devdoc>
  145.         /// A constructor for ReflectPropertyDescriptors that have no attributes.
  146.         /// </devdoc>
  147.         public ReflectPropertyDescriptor(Type componentClass, string name, Type type, PropertyInfo propInfo, MethodInfo getMethod, MethodInfo setMethod, Attribute[] attrs) : this(componentClass, name, type, attrs)
  148.         {
  149.             this.propInfo = propInfo;
  150.             this.getMethod = getMethod;
  151.             this.setMethod = setMethod;
  152.             if (getMethod != null && propInfo != null && setMethod == null)
  153.                 state[BitGetQueried | BitSetOnDemand] = true;
  154.             else
  155.                 state[BitGetQueried | BitSetQueried] = true;
  156.         }
  157.        
  158.         /// <devdoc>
  159.         /// A constructor for ReflectPropertyDescriptors that creates an extender property.
  160.         /// </devdoc>
  161.         public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Type receiverType, MethodInfo getMethod, MethodInfo setMethod, Attribute[] attrs) : this(componentClass, name, type, attrs)
  162.         {
  163.             this.receiverType = receiverType;
  164.             this.getMethod = getMethod;
  165.             this.setMethod = setMethod;
  166.             state[BitGetQueried | BitSetQueried] = true;
  167.         }
  168.        
  169.         /// <devdoc>
  170.         /// This constructor takes an existing ReflectPropertyDescriptor and modifies it by merging in the
  171.         /// passed-in attributes.
  172.         /// </devdoc>
  173.         public ReflectPropertyDescriptor(Type componentClass, PropertyDescriptor oldReflectPropertyDescriptor, Attribute[] attributes) : base(oldReflectPropertyDescriptor, attributes)
  174.         {
  175.            
  176.             this.componentClass = componentClass;
  177.             this.type = oldReflectPropertyDescriptor.PropertyType;
  178.            
  179.             if (componentClass == null) {
  180.                 throw new ArgumentException(SR.GetString(SR.InvalidNullArgument, "componentClass"));
  181.             }
  182.            
  183.             // If the classes are the same, we can potentially optimize the method fetch because
  184.             // the old property descriptor may already have it.
  185.             //
  186.             ReflectPropertyDescriptor oldProp = oldReflectPropertyDescriptor as ReflectPropertyDescriptor;
  187.             if (oldProp != null) {
  188.                 if (oldProp.ComponentType == componentClass) {
  189.                     propInfo = oldProp.propInfo;
  190.                     getMethod = oldProp.getMethod;
  191.                     setMethod = oldProp.setMethod;
  192.                     shouldSerializeMethod = oldProp.shouldSerializeMethod;
  193.                     resetMethod = oldProp.resetMethod;
  194.                     defaultValue = oldProp.defaultValue;
  195.                     ambientValue = oldProp.ambientValue;
  196.                     state = oldProp.state;
  197.                 }
  198.                
  199.                 // Now we must figure out what to do with our default value. First, check to see
  200.                 // if the caller has provided an new default value attribute. If so, use it. Otherwise,
  201.                 // just let it be and it will be picked up on demand.
  202.                 //
  203.                 if (attributes != null) {
  204.                     foreach (Attribute a in attributes) {
  205.                         DefaultValueAttribute dva = a as DefaultValueAttribute;
  206.                        
  207.                         if (dva != null) {
  208.                             defaultValue = dva.Value;
  209.                             state[BitDefaultValueQueried] = true;
  210.                         }
  211.                         else {
  212.                             AmbientValueAttribute ava = a as AmbientValueAttribute;
  213.                             if (ava != null) {
  214.                                 ambientValue = ava.Value;
  215.                                 state[BitAmbientValueQueried] = true;
  216.                             }
  217.                         }
  218.                     }
  219.                 }
  220.             }
  221.             #if DEBUG
  222.             else if (oldReflectPropertyDescriptor is DebugReflectPropertyDescriptor) {
  223.                 DebugReflectPropertyDescriptor oldProp1 = (DebugReflectPropertyDescriptor)oldReflectPropertyDescriptor;
  224.                
  225.                 if (oldProp1.ComponentType == componentClass) {
  226.                     propInfo = oldProp1.propInfo;
  227.                     getMethod = oldProp1.getMethod;
  228.                     setMethod = oldProp1.setMethod;
  229.                     shouldSerializeMethod = oldProp1.shouldSerializeMethod;
  230.                     resetMethod = oldProp1.resetMethod;
  231.                     defaultValue = oldProp1.defaultValue;
  232.                     ambientValue = oldProp1.ambientValue;
  233.                     state = oldProp1.state;
  234.                 }
  235.                
  236.                 // Now we must figure out what to do with our default value. First, check to see
  237.                 // if the caller has provided an new default value attribute. If so, use it. Otherwise,
  238.                 // just let it be and it will be picked up on demand.
  239.                 //
  240.                 if (attributes != null) {
  241.                     foreach (Attribute a in attributes) {
  242.                         if (a is DefaultValueAttribute) {
  243.                             defaultValue = ((DefaultValueAttribute)a).Value;
  244.                             state[BitDefaultValueQueried] = true;
  245.                         }
  246.                         else if (a is AmbientValueAttribute) {
  247.                             ambientValue = ((AmbientValueAttribute)a).Value;
  248.                             state[BitAmbientValueQueried] = true;
  249.                         }
  250.                     }
  251.                 }
  252.             }
  253.             #endif
  254.         }
  255.        
  256.         /// <devdoc>
  257.         /// Retrieves the ambient value for this property.
  258.         /// </devdoc>
  259.         private object AmbientValue {
  260.             get {
  261.                 if (!state[BitAmbientValueQueried]) {
  262.                     state[BitAmbientValueQueried] = true;
  263.                     Attribute a = Attributes[typeof(AmbientValueAttribute)];
  264.                     if (a != null) {
  265.                         ambientValue = ((AmbientValueAttribute)a).Value;
  266.                     }
  267.                     else {
  268.                         ambientValue = noValue;
  269.                     }
  270.                 }
  271.                 return ambientValue;
  272.             }
  273.         }
  274.        
  275.         /// <devdoc>
  276.         /// The EventDescriptor for the "{propertyname}Changed" event on the component, or null if there isn't one for this property.
  277.         /// </devdoc>
  278.         private EventDescriptor ChangedEventValue {
  279.             get {
  280.                 if (!state[BitChangedQueried]) {
  281.                     state[BitChangedQueried] = true;
  282.                     realChangedEvent = TypeDescriptor.GetEvents(ComponentType)[string.Format(CultureInfo.InvariantCulture, "{0}Changed", Name)];
  283.                 }
  284.                
  285.                 return realChangedEvent;
  286.             }
  287.         }
  288.        
  289. /*
  290.             The following code has been removed to fix FXCOP violations.  The code
  291.             is left here incase it needs to be resurrected in the future.
  292.             set {
  293.                 realChangedEvent = value;
  294.                 state[BitChangedQueried] = true;
  295.             }
  296.             */       
  297.        
  298.         /// <devdoc>
  299.         /// The EventDescriptor for the INotifyPropertyChanged.PropertyChanged event on the component, or null if there isn't one for this property.
  300.         /// </devdoc>
  301.         private EventDescriptor IPropChangedEventValue {
  302.             get {
  303.                 if (!state[BitIPropChangedQueried]) {
  304.                     state[BitIPropChangedQueried] = true;
  305.                    
  306.                     if (typeof(INotifyPropertyChanged).IsAssignableFrom(ComponentType)) {
  307.                         realIPropChangedEvent = TypeDescriptor.GetEvents(typeof(INotifyPropertyChanged))["PropertyChanged"];
  308.                     }
  309.                 }
  310.                
  311.                 return realIPropChangedEvent;
  312.             }
  313.             set {
  314.                 realIPropChangedEvent = value;
  315.                 state[BitIPropChangedQueried] = true;
  316.             }
  317.         }
  318.        
  319.         /// <devdoc>
  320.         /// Retrieves the type of the component this PropertyDescriptor is bound to.
  321.         /// </devdoc>
  322.         public override Type ComponentType {
  323.             get { return componentClass; }
  324.         }
  325.        
  326.         /// <devdoc>
  327.         /// Retrieves the default value for this property.
  328.         /// </devdoc>
  329.         private object DefaultValue {
  330.             get {
  331.                 if (!state[BitDefaultValueQueried]) {
  332.                     state[BitDefaultValueQueried] = true;
  333.                     Attribute a = Attributes[typeof(DefaultValueAttribute)];
  334.                     if (a != null) {
  335.                         defaultValue = ((DefaultValueAttribute)a).Value;
  336.                     }
  337.                     else {
  338.                         defaultValue = noValue;
  339.                     }
  340.                 }
  341.                 return defaultValue;
  342.             }
  343.         }
  344.        
  345.         /// <devdoc>
  346.         /// The GetMethod for this property
  347.         /// </devdoc>
  348.         private MethodInfo GetMethodValue {
  349.             get {
  350.                 if (!state[BitGetQueried]) {
  351.                     state[BitGetQueried] = true;
  352.                    
  353.                     if (receiverType == null) {
  354.                         if (propInfo == null) {
  355.                             BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty;
  356.                             propInfo = componentClass.GetProperty(Name, bindingFlags, null, PropertyType, new Type[0], new ParameterModifier[0]);
  357.                         }
  358.                         if (propInfo != null) {
  359.                             getMethod = propInfo.GetGetMethod(true);
  360.                         }
  361.                         if (getMethod == null) {
  362.                             throw new InvalidOperationException(SR.GetString(SR.ErrorMissingPropertyAccessors, componentClass.FullName + "." + Name));
  363.                         }
  364.                     }
  365.                     else {
  366.                         getMethod = FindMethod(componentClass, "Get" + Name, new Type[] {receiverType}, type);
  367.                         if (getMethod == null) {
  368.                             throw new ArgumentException(SR.GetString(SR.ErrorMissingPropertyAccessors, Name));
  369.                         }
  370.                     }
  371.                 }
  372.                 return getMethod;
  373.             }
  374.         }
  375.        
  376. /*
  377.             The following code has been removed to fix FXCOP violations.  The code
  378.             is left here incase it needs to be resurrected in the future.
  379.             set {
  380.                 state[BitGetQueried] = true;
  381.                 getMethod = value;
  382.             }
  383.             */       
  384.        
  385.         /// <devdoc>
  386.         /// Determines if this property is an extender property.
  387.         /// </devdoc>
  388.         private bool IsExtender {
  389.             get { return (receiverType != null); }
  390.         }
  391.        
  392.         /// <devdoc>
  393.         /// Indicates whether this property is read only.
  394.         /// </devdoc>
  395.         public override bool IsReadOnly {
  396.             get { return SetMethodValue == null || ((ReadOnlyAttribute)Attributes[typeof(ReadOnlyAttribute)]).IsReadOnly; }
  397.         }
  398.        
  399.        
  400.         /// <devdoc>
  401.         /// Retrieves the type of the property.
  402.         /// </devdoc>
  403.         public override Type PropertyType {
  404.             get { return type; }
  405.         }
  406.        
  407.         /// <devdoc>
  408.         /// Access to the reset method, if one exists for this property.
  409.         /// </devdoc>
  410.         private MethodInfo ResetMethodValue {
  411.             get {
  412.                 if (!state[BitResetQueried]) {
  413.                     state[BitResetQueried] = true;
  414.                    
  415.                     Type[] args;
  416.                    
  417.                     if (receiverType == null) {
  418.                         args = argsNone;
  419.                     }
  420.                     else {
  421.                         args = new Type[] {receiverType};
  422.                     }
  423.                    
  424.                     IntSecurity.FullReflection.Assert();
  425.                     try {
  426.                             /* publicOnly= */                        resetMethod = FindMethod(componentClass, "Reset" + Name, args, typeof(void), false);
  427.                     }
  428.                     finally {
  429.                         CodeAccessPermission.RevertAssert();
  430.                     }
  431.                 }
  432.                 return resetMethod;
  433.             }
  434.         }
  435.        
  436. /*
  437.             The following code has been removed to fix FXCOP violations.  The code
  438.             is left here incase it needs to be resurrected in the future.
  439.             set {
  440.                 state[BitResetQueried] = true;
  441.                 resetMethod = value;
  442.             }
  443.             */       
  444.        
  445.         /// <devdoc>
  446.         /// Accessor for the set method
  447.         /// </devdoc>
  448.         private MethodInfo SetMethodValue {
  449.             get {
  450.                 if (!state[BitSetQueried] && state[BitSetOnDemand]) {
  451.                     state[BitSetQueried] = true;
  452.                    
  453.                     BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
  454.                     string name = propInfo.Name;
  455.                    
  456.                     if (setMethod == null) {
  457.                         for (Type t = ComponentType.BaseType; t != null && t != typeof(object); t = t.BaseType) {
  458.                             if (t == null) {
  459.                                 break;
  460.                             }
  461.                             PropertyInfo p = t.GetProperty(name, bindingFlags, null, PropertyType, new Type[0], null);
  462.                             if (p != null) {
  463.                                 setMethod = p.GetSetMethod();
  464.                                 if (setMethod != null) {
  465.                                     break;
  466.                                 }
  467.                             }
  468.                         }
  469.                     }
  470.                    
  471.                 }
  472.                 if (!state[BitSetQueried]) {
  473.                     state[BitSetQueried] = true;
  474.                    
  475.                     if (receiverType == null) {
  476.                         if (propInfo == null) {
  477.                             BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty;
  478.                             propInfo = componentClass.GetProperty(Name, bindingFlags, null, PropertyType, new Type[0], new ParameterModifier[0]);
  479.                         }
  480.                         if (propInfo != null) {
  481.                             setMethod = propInfo.GetSetMethod(true);
  482.                         }
  483.                     }
  484.                     else {
  485.                         setMethod = FindMethod(componentClass, "Set" + Name, new Type[] {receiverType, type}, typeof(void));
  486.                     }
  487.                 }
  488.                 return setMethod;
  489.             }
  490.         }
  491.        
  492. /*
  493.             The following code has been removed to fix FXCOP violations.  The code
  494.             is left here incase it needs to be resurrected in the future.
  495.             set {
  496.                 state[BitSetQueried] = true;
  497.                 setMethod = value;
  498.             }
  499.             */       
  500.        
  501.         /// <devdoc>
  502.         /// Accessor for the ShouldSerialize method.
  503.         /// </devdoc>
  504.         private MethodInfo ShouldSerializeMethodValue {
  505.             get {
  506.                 if (!state[BitShouldSerializeQueried]) {
  507.                     state[BitShouldSerializeQueried] = true;
  508.                    
  509.                     Type[] args;
  510.                    
  511.                     if (receiverType == null) {
  512.                         args = argsNone;
  513.                     }
  514.                     else {
  515.                         args = new Type[] {receiverType};
  516.                     }
  517.                    
  518.                     IntSecurity.FullReflection.Assert();
  519.                     try {
  520.                             /* publicOnly= */                        shouldSerializeMethod = FindMethod(componentClass, "ShouldSerialize" + Name, args, typeof(bool), false);
  521.                     }
  522.                     finally {
  523.                         CodeAccessPermission.RevertAssert();
  524.                     }
  525.                 }
  526.                 return shouldSerializeMethod;
  527.             }
  528.         }
  529.        
  530. /*
  531.             The following code has been removed to fix FXCOP violations.  The code
  532.             is left here incase it needs to be resurrected in the future.
  533.             set {
  534.                 state[BitShouldSerializeQueried] = true;
  535.                 shouldSerializeMethod = value;
  536.             }
  537.             */       
  538.        
  539.         /// <devdoc>
  540.         /// Allows interested objects to be notified when this property changes.
  541.         /// </devdoc>
  542.         public override void AddValueChanged(object component, EventHandler handler)
  543.         {
  544.             if (component == null)
  545.                 throw new ArgumentNullException("component");
  546.             if (handler == null)
  547.                 throw new ArgumentNullException("handler");
  548.            
  549.             // If there's an event called <propertyname>Changed, hook the caller's handler directly up to that on the component
  550.             EventDescriptor changedEvent = ChangedEventValue;
  551.             if (changedEvent != null && changedEvent.EventType.IsInstanceOfType(handler)) {
  552.                 changedEvent.AddEventHandler(component, handler);
  553.             }
  554.            
  555.             // Otherwise let the base class add the handler to its ValueChanged event for this component
  556.             else {
  557.                
  558.                 // Special case: If this will be the FIRST handler added for this component, and the component implements
  559.                 // INotifyPropertyChanged, the property descriptor must START listening to the generic PropertyChanged event
  560.                 if (GetValueChangedHandler(component) == null) {
  561.                     EventDescriptor iPropChangedEvent = IPropChangedEventValue;
  562.                     if (iPropChangedEvent != null) {
  563.                         iPropChangedEvent.AddEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
  564.                     }
  565.                 }
  566.                
  567.                 base.AddValueChanged(component, handler);
  568.             }
  569.         }
  570.        
  571.         internal bool ExtenderCanResetValue(IExtenderProvider provider, object component)
  572.         {
  573.             if (DefaultValue != noValue) {
  574.                 return !object.Equals(ExtenderGetValue(provider, component), defaultValue);
  575.             }
  576.            
  577.             MethodInfo reset = ResetMethodValue;
  578.             if (reset != null) {
  579.                 MethodInfo shouldSerialize = ShouldSerializeMethodValue;
  580.                 if (shouldSerialize != null) {
  581.                     try {
  582.                         provider = (IExtenderProvider)GetInvocationTarget(componentClass, provider);
  583.                         return (bool)shouldSerialize.Invoke(provider, new object[] {component});
  584.                     }
  585.                     catch {
  586.                     }
  587.                 }
  588.                 return true;
  589.             }
  590.            
  591.             return false;
  592.         }
  593.        
  594.         internal Type ExtenderGetReceiverType()
  595.         {
  596.             return receiverType;
  597.         }
  598.        
  599.         internal Type ExtenderGetType(IExtenderProvider provider)
  600.         {
  601.             return PropertyType;
  602.         }
  603.        
  604.         internal object ExtenderGetValue(IExtenderProvider provider, object component)
  605.         {
  606.             if (provider != null) {
  607.                 provider = (IExtenderProvider)GetInvocationTarget(componentClass, provider);
  608.                 return GetMethodValue.Invoke(provider, new object[] {component});
  609.             }
  610.             return null;
  611.         }
  612.        
  613.         internal void ExtenderResetValue(IExtenderProvider provider, object component, PropertyDescriptor notifyDesc)
  614.         {
  615.             if (DefaultValue != noValue) {
  616.                 ExtenderSetValue(provider, component, DefaultValue, notifyDesc);
  617.             }
  618.             else if (AmbientValue != noValue) {
  619.                 ExtenderSetValue(provider, component, AmbientValue, notifyDesc);
  620.             }
  621.             else if (ResetMethodValue != null) {
  622.                 ISite site = GetSite(component);
  623.                 IComponentChangeService changeService = null;
  624.                 object oldValue = null;
  625.                 object newValue;
  626.                
  627.                 // Announce that we are about to change this component
  628.                 //
  629.                 if (site != null) {
  630.                     changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
  631.                     Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
  632.                 }
  633.                
  634.                 // Make sure that it is ok to send the onchange events
  635.                 //
  636.                 if (changeService != null) {
  637.                     oldValue = ExtenderGetValue(provider, component);
  638.                     try {
  639.                         changeService.OnComponentChanging(component, notifyDesc);
  640.                     }
  641.                     catch (CheckoutException coEx) {
  642.                         if (coEx == CheckoutException.Canceled) {
  643.                             return;
  644.                         }
  645.                         throw coEx;
  646.                     }
  647.                 }
  648.                
  649.                 provider = (IExtenderProvider)GetInvocationTarget(componentClass, provider);
  650.                 if (ResetMethodValue != null) {
  651.                     ResetMethodValue.Invoke(provider, new object[] {component});
  652.                    
  653.                     // Now notify the change service that the change was successful.
  654.                     //
  655.                     if (changeService != null) {
  656.                         newValue = ExtenderGetValue(provider, component);
  657.                         changeService.OnComponentChanged(component, notifyDesc, oldValue, newValue);
  658.                     }
  659.                 }
  660.             }
  661.         }
  662.        
  663.         internal void ExtenderSetValue(IExtenderProvider provider, object component, object value, PropertyDescriptor notifyDesc)
  664.         {
  665.             if (provider != null) {
  666.                
  667.                 ISite site = GetSite(component);
  668.                 IComponentChangeService changeService = null;
  669.                 object oldValue = null;
  670.                
  671.                 // Announce that we are about to change this component
  672.                 //
  673.                 if (site != null) {
  674.                     changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
  675.                     Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
  676.                 }
  677.                
  678.                 // Make sure that it is ok to send the onchange events
  679.                 //
  680.                 if (changeService != null) {
  681.                     oldValue = ExtenderGetValue(provider, component);
  682.                     try {
  683.                         changeService.OnComponentChanging(component, notifyDesc);
  684.                     }
  685.                     catch (CheckoutException coEx) {
  686.                         if (coEx == CheckoutException.Canceled) {
  687.                             return;
  688.                         }
  689.                         throw coEx;
  690.                     }
  691.                 }
  692.                
  693.                 provider = (IExtenderProvider)GetInvocationTarget(componentClass, provider);
  694.                
  695.                 if (SetMethodValue != null) {
  696.                     SetMethodValue.Invoke(provider, new object[] {component, value});
  697.                    
  698.                     // Now notify the change service that the change was successful.
  699.                     //
  700.                     if (changeService != null) {
  701.                         changeService.OnComponentChanged(component, notifyDesc, oldValue, value);
  702.                     }
  703.                 }
  704.             }
  705.         }
  706.        
  707.         internal bool ExtenderShouldSerializeValue(IExtenderProvider provider, object component)
  708.         {
  709.            
  710.            
  711.             provider = (IExtenderProvider)GetInvocationTarget(componentClass, provider);
  712.            
  713.             if (IsReadOnly) {
  714.                 if (ShouldSerializeMethodValue != null) {
  715.                     try {
  716.                         return (bool)ShouldSerializeMethodValue.Invoke(provider, new object[] {component});
  717.                     }
  718.                     catch {
  719.                     }
  720.                 }
  721.                 return Attributes.Contains(DesignerSerializationVisibilityAttribute.Content);
  722.             }
  723.             else if (DefaultValue == noValue) {
  724.                 if (ShouldSerializeMethodValue != null) {
  725.                     try {
  726.                         return (bool)ShouldSerializeMethodValue.Invoke(provider, new object[] {component});
  727.                     }
  728.                     catch {
  729.                     }
  730.                 }
  731.                 return true;
  732.             }
  733.             return !object.Equals(DefaultValue, ExtenderGetValue(provider, component));
  734.         }
  735.        
  736.         /// <devdoc>
  737.         /// Indicates whether reset will change the value of the component. If there
  738.         /// is a DefaultValueAttribute, then this will return true if getValue returns
  739.         /// something different than the default value. If there is a reset method and
  740.         /// a ShouldSerialize method, this will return what ShouldSerialize returns.
  741.         /// If there is just a reset method, this always returns true. If none of these
  742.         /// cases apply, this returns false.
  743.         /// </devdoc>
  744.         public override bool CanResetValue(object component)
  745.         {
  746.             if (IsExtender || IsReadOnly) {
  747.                 return false;
  748.             }
  749.            
  750.             if (DefaultValue != noValue) {
  751.                 return !object.Equals(GetValue(component), DefaultValue);
  752.             }
  753.            
  754.             if (ResetMethodValue != null) {
  755.                 if (ShouldSerializeMethodValue != null) {
  756.                     component = GetInvocationTarget(componentClass, component);
  757.                     try {
  758.                         return (bool)ShouldSerializeMethodValue.Invoke(component, null);
  759.                     }
  760.                     catch {
  761.                     }
  762.                 }
  763.                 return true;
  764.             }
  765.            
  766.             if (AmbientValue != noValue) {
  767.                 return ShouldSerializeValue(component);
  768.             }
  769.            
  770.             return false;
  771.         }
  772.        
  773.         protected override void FillAttributes(IList attributes)
  774.         {
  775.             Debug.Assert(componentClass != null, "Must have a component class for FillAttributes");
  776.            
  777.             //
  778.             // The order that we fill in attributes is critical. The list of attributes will be
  779.             // filtered so that matching attributes at the end of the list replace earlier matches
  780.             // (last one in wins). Therefore, the four categories of attributes we add must be
  781.             // added as follows:
  782.             //
  783.             // 1. Attributes of the property type. These are the lowest level and should be
  784.             // overwritten by any newer attributes.
  785.             //
  786.             // 2. Attributes obtained from any SpecificTypeAttribute. These supercede attributes
  787.             // for the property type.
  788.             //
  789.             // 3. Attributes of the property itself, from base class to most derived. This way
  790.             // derived class attributes replace base class attributes.
  791.             //
  792.             // 4. Attributes from our base MemberDescriptor. While this seems opposite of what
  793.             // we want, MemberDescriptor only has attributes if someone passed in a new
  794.             // set in the constructor. Therefore, these attributes always
  795.             // supercede existing values.
  796.             //
  797.            
  798.            
  799.             // We need to include attributes from the type of the property.
  800.             //
  801.             foreach (Attribute typeAttr in TypeDescriptor.GetAttributes(PropertyType)) {
  802.                 attributes.Add(typeAttr);
  803.             }
  804.            
  805.             // NOTE : Must look at method OR property, to handle the case of Extender properties...
  806.             //
  807.             // Note : Because we are using BindingFlags.DeclaredOnly it is more effcient to re-aquire
  808.             // : the property info, rather than use the one we have cached. The one we have cached
  809.             // : may ave come from a base class, meaning we will request custom metadata for this
  810.             // : class twice.
  811.            
  812.             BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly;
  813.             Type currentReflectType = componentClass;
  814.             int depth = 0;
  815.            
  816.             // First, calculate the depth of the object hierarchy. We do this so we can do a single
  817.             // object create for an array of attributes.
  818.             //
  819.             while (currentReflectType != null && currentReflectType != typeof(object)) {
  820.                 depth++;
  821.                 currentReflectType = currentReflectType.BaseType;
  822.             }
  823.            
  824.             // Now build up an array in reverse order
  825.             //
  826.             if (depth > 0) {
  827.                 currentReflectType = componentClass;
  828.                 Attribute[][] attributeStack = new Attribute[depth][];
  829.                
  830.                 while (currentReflectType != null && currentReflectType != typeof(object)) {
  831.                    
  832.                     MemberInfo memberInfo = null;
  833.                    
  834.                     // Fill in our member info so we can get at the custom attributes.
  835.                     //
  836.                     if (IsExtender) {
  837.                         memberInfo = currentReflectType.GetMethod("Get" + Name, bindingFlags);
  838.                     }
  839.                     else {
  840.                         memberInfo = currentReflectType.GetProperty(Name, bindingFlags, null, PropertyType, new Type[0], new ParameterModifier[0]);
  841.                     }
  842.                    
  843.                     // Get custom attributes for the member info.
  844.                     //
  845.                     if (memberInfo != null) {
  846.                         attributeStack[--depth] = ReflectTypeDescriptionProvider.ReflectGetAttributes(memberInfo);
  847.                     }
  848.                    
  849.                     // Ready for the next loop iteration.
  850.                     //
  851.                     currentReflectType = currentReflectType.BaseType;
  852.                 }
  853.                
  854.                 // Look in the attribute stack for AttributeProviders
  855.                 //
  856.                 foreach (Attribute[] attributeArray in attributeStack) {
  857.                     if (attributeArray != null) {
  858.                         foreach (Attribute attr in attributeArray) {
  859.                             AttributeProviderAttribute sta = attr as AttributeProviderAttribute;
  860.                             if (sta != null) {
  861.                                 Type specificType = Type.GetType(sta.TypeName);
  862.                                
  863.                                 if (specificType != null) {
  864.                                     Attribute[] stAttrs = null;
  865.                                    
  866.                                     if (!String.IsNullOrEmpty(sta.PropertyName)) {
  867.                                         MemberInfo[] milist = specificType.GetMember(sta.PropertyName);
  868.                                         if (milist.Length > 0 && milist[0] != null) {
  869.                                             stAttrs = ReflectTypeDescriptionProvider.ReflectGetAttributes(milist[0]);
  870.                                         }
  871.                                     }
  872.                                     else {
  873.                                         stAttrs = ReflectTypeDescriptionProvider.ReflectGetAttributes(specificType);
  874.                                     }
  875.                                     if (stAttrs != null) {
  876.                                         foreach (Attribute stAttr in stAttrs) {
  877.                                             attributes.Add(stAttr);
  878.                                         }
  879.                                     }
  880.                                 }
  881.                             }
  882.                         }
  883.                     }
  884.                 }
  885.                
  886.                 // Now trawl the attribute stack so that we add attributes
  887.                 // from base class to most derived.
  888.                 //
  889.                 foreach (Attribute[] attributeArray in attributeStack) {
  890.                     if (attributeArray != null) {
  891.                         foreach (Attribute attr in attributeArray) {
  892.                             attributes.Add(attr);
  893.                         }
  894.                     }
  895.                 }
  896.             }
  897.            
  898.             // Include the base attributes. These override all attributes on the actual
  899.             // property, so we want to add them last.
  900.             //
  901.             base.FillAttributes(attributes);
  902.            
  903.             // Finally, override any form of ReadOnlyAttribute.
  904.             //
  905.             if (SetMethodValue == null) {
  906.                 attributes.Add(ReadOnlyAttribute.Yes);
  907.             }
  908.         }
  909.        
  910.         /// <devdoc>
  911.         /// Retrieves the current value of the property on component,
  912.         /// invoking the getXXX method. An exception in the getXXX
  913.         /// method will pass through.
  914.         /// </devdoc>
  915.         public override object GetValue(object component)
  916.         {
  917.             #if DEBUG
  918.             if (PropDescUsageSwitch.TraceVerbose) {
  919.                 string compName = "(null)";
  920.                 if (component != null)
  921.                     compName = component.ToString();
  922.                
  923.                 Debug.WriteLine("[" + Name + "]: GetValue(" + compName + ")");
  924.             }
  925.             #endif
  926.            
  927.             if (IsExtender) {
  928.                 Debug.WriteLineIf(PropDescUsageSwitch.TraceVerbose, "[" + Name + "]: ---> returning: null");
  929.                 return null;
  930.             }
  931.            
  932.             Debug.Assert(component != null, "GetValue must be given a component");
  933.            
  934.             if (component != null) {
  935.                 component = GetInvocationTarget(componentClass, component);
  936.                
  937.                
  938.                 try {
  939.                     return GetMethodValue.Invoke(component, null);
  940.                 }
  941.                 catch (Exception t) {
  942.                    
  943.                     string name = null;
  944.                     IComponent comp = component as IComponent;
  945.                     if (comp != null) {
  946.                         ISite site = comp.Site;
  947.                         if (site != null && site.Name != null) {
  948.                             name = site.Name;
  949.                         }
  950.                     }
  951.                    
  952.                     if (name == null) {
  953.                         name = component.GetType().FullName;
  954.                     }
  955.                    
  956.                     if (t is TargetInvocationException) {
  957.                         t = t.InnerException;
  958.                     }
  959.                    
  960.                     string message = t.Message;
  961.                     if (message == null) {
  962.                         message = t.GetType().Name;
  963.                     }
  964.                    
  965.                     throw new TargetInvocationException(SR.GetString(SR.ErrorPropertyAccessorException, Name, name, message), t);
  966.                 }
  967.             }
  968.             Debug.WriteLineIf(PropDescUsageSwitch.TraceVerbose, "[" + Name + "]: ---> returning: null");
  969.             return null;
  970.         }
  971.        
  972.         /// <devdoc>
  973.         /// Handles INotifyPropertyChanged.PropertyChange events from components.
  974.         /// If event pertains to this property, issue a ValueChanged event.
  975.         /// </devdoc>
  976.         /// </internalonly>
  977.         internal void OnINotifyPropertyChanged(object component, PropertyChangedEventArgs e)
  978.         {
  979.             if (String.IsNullOrEmpty(e.PropertyName) || String.Compare(e.PropertyName, Name, true, System.Globalization.CultureInfo.InvariantCulture) == 0) {
  980.                 OnValueChanged(component, e);
  981.             }
  982.         }
  983.        
  984.         /// <devdoc>
  985.         /// This should be called by your property descriptor implementation
  986.         /// when the property value has changed.
  987.         /// </devdoc>
  988.         protected override void OnValueChanged(object component, EventArgs e)
  989.         {
  990.             if (state[BitChangedQueried] && realChangedEvent == null) {
  991.                 base.OnValueChanged(component, e);
  992.             }
  993.         }
  994.        
  995.         /// <devdoc>
  996.         /// Allows interested objects to be notified when this property changes.
  997.         /// </devdoc>
  998.         public override void RemoveValueChanged(object component, EventHandler handler)
  999.         {
  1000.             if (component == null)
  1001.                 throw new ArgumentNullException("component");
  1002.             if (handler == null)
  1003.                 throw new ArgumentNullException("handler");
  1004.            
  1005.             // If there's an event called <propertyname>Changed, we hooked the caller's
  1006.             // handler directly up to that on the component, so remove it now.
  1007.             EventDescriptor changedEvent = ChangedEventValue;
  1008.             if (changedEvent != null) {
  1009.                 changedEvent.RemoveEventHandler(component, handler);
  1010.             }
  1011.            
  1012.             // Otherwise the base class added the handler to its ValueChanged
  1013.             // event for this component, so let the base class remove it now.
  1014.             else {
  1015.                 base.RemoveValueChanged(component, handler);
  1016.                
  1017.                 // Special case: If that was the LAST handler removed for this component, and the component implements
  1018.                 // INotifyPropertyChanged, the property descriptor must STOP listening to the generic PropertyChanged event
  1019.                 if (GetValueChangedHandler(component) == null) {
  1020.                     EventDescriptor iPropChangedEvent = IPropChangedEventValue;
  1021.                     if (iPropChangedEvent != null) {
  1022.                         iPropChangedEvent.RemoveEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
  1023.                     }
  1024.                 }
  1025.             }
  1026.         }
  1027.        
  1028.         /// <devdoc>
  1029.         /// Will reset the default value for this property on the component. If
  1030.         /// there was a default value passed in as a DefaultValueAttribute, that
  1031.         /// value will be set as the value of the property on the component. If
  1032.         /// there was no default value passed in, a ResetXXX method will be looked
  1033.         /// for. If one is found, it will be invoked. If one is not found, this
  1034.         /// is a nop.
  1035.         /// </devdoc>
  1036.         public override void ResetValue(object component)
  1037.         {
  1038.             object invokee = GetInvocationTarget(componentClass, component);
  1039.            
  1040.             if (DefaultValue != noValue) {
  1041.                 SetValue(component, DefaultValue);
  1042.             }
  1043.             else if (AmbientValue != noValue) {
  1044.                 SetValue(component, AmbientValue);
  1045.             }
  1046.             else if (ResetMethodValue != null) {
  1047.                 ISite site = GetSite(component);
  1048.                 IComponentChangeService changeService = null;
  1049.                 object oldValue = null;
  1050.                 object newValue;
  1051.                
  1052.                 // Announce that we are about to change this component
  1053.                 //
  1054.                 if (site != null) {
  1055.                     changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
  1056.                     Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
  1057.                 }
  1058.                
  1059.                 // Make sure that it is ok to send the onchange events
  1060.                 //
  1061.                 if (changeService != null) {
  1062.                     oldValue = GetMethodValue.Invoke(invokee, (object[])null);
  1063.                     try {
  1064.                         changeService.OnComponentChanging(component, this);
  1065.                     }
  1066.                     catch (CheckoutException coEx) {
  1067.                         if (coEx == CheckoutException.Canceled) {
  1068.                             return;
  1069.                         }
  1070.                         throw coEx;
  1071.                     }
  1072.                    
  1073.                 }
  1074.                
  1075.                 if (ResetMethodValue != null) {
  1076.                     ResetMethodValue.Invoke(invokee, (object[])null);
  1077.                    
  1078.                     // Now notify the change service that the change was successful.
  1079.                     //
  1080.                     if (changeService != null) {
  1081.                         newValue = GetMethodValue.Invoke(invokee, (object[])null);
  1082.                         changeService.OnComponentChanged(component, this, oldValue, newValue);
  1083.                     }
  1084.                 }
  1085.             }
  1086.         }
  1087.        
  1088.         /// <devdoc>
  1089.         /// This will set value to be the new value of this property on the
  1090.         /// component by invoking the setXXX method on the component. If the
  1091.         /// value specified is invalid, the component should throw an exception
  1092.         /// which will be passed up. The component designer should design the
  1093.         /// property so that getXXX following a setXXX should return the value
  1094.         /// passed in if no exception was thrown in the setXXX call.
  1095.         /// </devdoc>
  1096.         public override void SetValue(object component, object value)
  1097.         {
  1098.             #if DEBUG
  1099.             if (PropDescUsageSwitch.TraceVerbose) {
  1100.                 string compName = "(null)";
  1101.                 string valName = "(null)";
  1102.                
  1103.                 if (component != null)
  1104.                     compName = component.ToString();
  1105.                 if (value != null)
  1106.                     valName = value.ToString();
  1107.                
  1108.                 Debug.WriteLine("[" + Name + "]: SetValue(" + compName + ", " + valName + ")");
  1109.             }
  1110.             #endif
  1111.             if (component != null) {
  1112.                 ISite site = GetSite(component);
  1113.                 IComponentChangeService changeService = null;
  1114.                 object oldValue = null;
  1115.                
  1116.                 object invokee = GetInvocationTarget(componentClass, component);
  1117.                
  1118.                 Debug.Assert(!IsReadOnly, "SetValue attempted on read-only property [" + Name + "]");
  1119.                 if (!IsReadOnly) {
  1120.                    
  1121.                     // Announce that we are about to change this component
  1122.                     //
  1123.                     if (site != null) {
  1124.                         changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
  1125.                         Debug.Assert(!CompModSwitches.CommonDesignerServices.Enabled || changeService != null, "IComponentChangeService not found");
  1126.                     }
  1127.                    
  1128.                    
  1129.                     // Make sure that it is ok to send the onchange events
  1130.                     //
  1131.                     if (changeService != null) {
  1132.                         oldValue = GetMethodValue.Invoke(invokee, null);
  1133.                         try {
  1134.                             changeService.OnComponentChanging(component, this);
  1135.                         }
  1136.                         catch (CheckoutException coEx) {
  1137.                             if (coEx == CheckoutException.Canceled) {
  1138.                                 return;
  1139.                             }
  1140.                             throw coEx;
  1141.                         }
  1142.                     }
  1143.                    
  1144.                     try {
  1145.                         try {
  1146.                             SetMethodValue.Invoke(invokee, new object[] {value});
  1147.                             OnValueChanged(invokee, EventArgs.Empty);
  1148.                         }
  1149.                         catch (Exception t) {
  1150.                             // Give ourselves a chance to unwind properly before rethrowing the exception.
  1151.                             //
  1152.                             value = oldValue;
  1153.                            
  1154.                             // If there was a problem setting the controls property then we get:
  1155.                             // ArgumentException (from properties set method)
  1156.                             // ==> Becomes inner exception of TargetInvocationException
  1157.                             // ==> caught here
  1158.                            
  1159.                             if (t is TargetInvocationException && t.InnerException != null) {
  1160.                                 // Propagate the original exception up
  1161.                                 throw t.InnerException;
  1162.                             }
  1163.                             else {
  1164.                                 throw t;
  1165.                             }
  1166.                         }
  1167.                     }
  1168.                     finally {
  1169.                         // Now notify the change service that the change was successful.
  1170.                         //
  1171.                         if (changeService != null) {
  1172.                             changeService.OnComponentChanged(component, this, oldValue, value);
  1173.                         }
  1174.                     }
  1175.                 }
  1176.             }
  1177.         }
  1178.        
  1179.         /// <devdoc>
  1180.         /// Indicates whether the value of this property needs to be persisted. In
  1181.         /// other words, it indicates whether the state of the property is distinct
  1182.         /// from when the component is first instantiated. If there is a default
  1183.         /// value specified in this ReflectPropertyDescriptor, it will be compared against the
  1184.         /// property's current value to determine this. If there is't, the
  1185.         /// ShouldSerializeXXX method is looked for and invoked if found. If both
  1186.         /// these routes fail, true will be returned.
  1187.         ///
  1188.         /// If this returns false, a tool should not persist this property's value.
  1189.         /// </devdoc>
  1190.         public override bool ShouldSerializeValue(object component)
  1191.         {
  1192.            
  1193.             component = GetInvocationTarget(componentClass, component);
  1194.            
  1195.             if (IsReadOnly) {
  1196.                 if (ShouldSerializeMethodValue != null) {
  1197.                     try {
  1198.                         return (bool)ShouldSerializeMethodValue.Invoke(component, null);
  1199.                     }
  1200.                     catch {
  1201.                     }
  1202.                 }
  1203.                 return Attributes.Contains(DesignerSerializationVisibilityAttribute.Content);
  1204.             }
  1205.             else if (DefaultValue == noValue) {
  1206.                 if (ShouldSerializeMethodValue != null) {
  1207.                     try {
  1208.                         return (bool)ShouldSerializeMethodValue.Invoke(component, null);
  1209.                     }
  1210.                     catch {
  1211.                     }
  1212.                 }
  1213.                 return true;
  1214.             }
  1215.             return !object.Equals(DefaultValue, GetValue(component));
  1216.         }
  1217.        
  1218.         /// <devdoc>
  1219.         /// Indicates whether value change notifications for this property may originate from outside the property
  1220.         /// descriptor, such as from the component itself (value=true), or whether notifications will only originate
  1221.         /// from direct calls made to PropertyDescriptor.SetValue (value=false). For example, the component may
  1222.         /// implement the INotifyPropertyChanged interface, or may have an explicit '{name}Changed' event for this property.
  1223.         /// </devdoc>
  1224.         public override bool SupportsChangeEvents {
  1225.             get { return IPropChangedEventValue != null || ChangedEventValue != null; }
  1226.         }
  1227.        
  1228.        
  1229.         /*
  1230.         The following code has been removed to fix FXCOP violations.  The code
  1231.         is left here incase it needs to be resurrected in the future.
  1232.         /// <devdoc>
  1233.         ///    A constructor for ReflectPropertyDescriptors that have no attributes.
  1234.         /// </devdoc>
  1235.         public ReflectPropertyDescriptor(Type componentClass, string name, Type type) : this(componentClass, name, type, (Attribute[])null) {
  1236.         }
  1237.         */       
  1238.     }
  1239. }

Developer Fusion