2 // System.ComponentModel.PropertyDescriptor.cs
5 // Lluis Sanchez Gual (lluis@ximian.com)
6 // Ivan N. Zlatev (contact i-nZ.net)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
35 using System.ComponentModel.Design;
37 namespace System.ComponentModel
39 internal class ReflectionPropertyDescriptor : PropertyDescriptor
44 public ReflectionPropertyDescriptor (Type componentType, PropertyDescriptor oldPropertyDescriptor, Attribute [] attributes)
45 : base (oldPropertyDescriptor, attributes)
47 _componentType = componentType;
50 public ReflectionPropertyDescriptor (Type componentType, string name, Type type, Attribute [] attributes)
51 : base (name, attributes)
53 _componentType = componentType;
56 public ReflectionPropertyDescriptor (PropertyInfo info)
57 : base (info.Name, (Attribute[])info.GetCustomAttributes (true))
60 _componentType = _member.DeclaringType;
63 PropertyInfo GetPropertyInfo ()
65 if (_member == null) {
66 _member = _componentType.GetProperty (Name, BindingFlags.GetProperty | BindingFlags.NonPublic |
67 BindingFlags.Public | BindingFlags.Instance);
69 throw new ArgumentException ("Accessor methods for the " + Name + " property are missing");
74 public override Type ComponentType {
75 get { return _componentType; }
78 public override bool IsReadOnly {
82 ReadOnlyAttribute attrib = ((ReadOnlyAttribute) Attributes[typeof (ReadOnlyAttribute)]);
84 attr_ro = attrib.IsReadOnly;
86 return !GetPropertyInfo ().CanWrite || attrib.IsReadOnly;
90 public override Type PropertyType {
92 return GetPropertyInfo ().PropertyType;
96 public override object GetValue (object component)
98 component = MemberDescriptor.GetInvokee (_componentType, component);
99 return GetPropertyInfo ().GetValue (component, null);
102 DesignerTransaction CreateTransaction (object obj, string description)
104 IComponent com = obj as IComponent;
105 if (com == null || com.Site == null)
108 IDesignerHost dh = (IDesignerHost) com.Site.GetService (typeof(IDesignerHost));
112 DesignerTransaction tran = dh.CreateTransaction (description);
113 IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
115 ccs.OnComponentChanging (com, this);
119 void EndTransaction (object obj, DesignerTransaction tran, object oldValue, object newValue, bool commit)
122 // FIXME: EventArgs might be differen type.
123 OnValueChanged (obj, new PropertyChangedEventArgs (Name));
128 IComponent com = obj as IComponent;
129 IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
131 ccs.OnComponentChanged (com, this, oldValue, newValue);
133 // FIXME: EventArgs might be differen type.
134 OnValueChanged (obj, new PropertyChangedEventArgs (Name));
139 public override void SetValue (object component, object value)
141 DesignerTransaction tran = CreateTransaction (component, "Set Property '" + Name + "'");
143 object propertyHolder = MemberDescriptor.GetInvokee (_componentType, component);
144 object old = GetValue (propertyHolder);
147 GetPropertyInfo ().SetValue (propertyHolder, value, null);
148 EndTransaction (component, tran, old, value, true);
150 EndTransaction (component, tran, old, value, false);
155 MethodInfo FindPropertyMethod (object o, string method_name)
157 MethodInfo mi = null;
158 string name = method_name + Name;
160 foreach (MethodInfo m in o.GetType().GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) {
161 // XXX should we really not check the return type of the method?
162 if (m.Name == name && m.GetParameters().Length == 0) {
171 public override void ResetValue (object component)
173 object propertyHolder = MemberDescriptor.GetInvokee (_componentType, component);
175 DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
177 SetValue (propertyHolder, attrib.Value);
179 DesignerTransaction tran = CreateTransaction (component, "Reset Property '" + Name + "'");
180 object old = GetValue (propertyHolder);
183 MethodInfo mi = FindPropertyMethod (propertyHolder, "Reset");
185 mi.Invoke (propertyHolder, null);
186 EndTransaction (component, tran, old, GetValue (propertyHolder), true);
188 EndTransaction (component, tran, old, GetValue (propertyHolder), false);
193 public override bool CanResetValue (object component)
195 component = MemberDescriptor.GetInvokee (_componentType, component);
197 DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
198 if (attrib != null) {
199 object current = GetValue (component);
200 if (attrib.Value == null || current == null){
201 if (attrib.Value != current)
203 if (attrib.Value == null && current == null)
207 return !attrib.Value.Equals (current);
210 if (!_member.CanWrite)
213 MethodInfo mi = FindPropertyMethod (component, "ShouldPersist");
215 return (bool) mi.Invoke (component, null);
217 mi = FindPropertyMethod (component, "ShouldSerialize");
218 if (mi != null && !((bool) mi.Invoke (component, null)))
221 mi = FindPropertyMethod (component, "Reset");
226 public override bool ShouldSerializeValue (object component)
228 component = MemberDescriptor.GetInvokee (_componentType, component);
231 MethodInfo mi = FindPropertyMethod (component, "ShouldSerialize");
233 return (bool) mi.Invoke (component, null);
234 return Attributes.Contains (DesignerSerializationVisibilityAttribute.Content);
237 DefaultValueAttribute attrib = ((DefaultValueAttribute) Attributes[typeof (DefaultValueAttribute)]);
238 if (attrib != null) {
239 object current = GetValue (component);
240 if (attrib.Value == null || current == null)
241 return attrib.Value != current;
242 return !attrib.Value.Equals (current);
245 MethodInfo mi = FindPropertyMethod (component, "ShouldSerialize");
247 return (bool) mi.Invoke (component, null);
248 // MSDN: If this method cannot find a DefaultValueAttribute or a ShouldSerializeMyProperty method,
249 // it cannot create optimizations and it returns true.