2008-11-17 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mcs / class / corlib / System.Reflection / MonoProperty.cs
1 //
2 // System.Reflection/MonoProperty.cs
3 // The class used to represent Properties from the mono runtime.
4 //
5 // Author:
6 //   Paolo Molaro (lupus@ximian.com)
7 //   Patrik Torstensson (patrik.torstensson@labs2.com)
8 //
9 // (C) 2001 Ximian, Inc.  http://www.ximian.com
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Globalization;
33 using System.Runtime.CompilerServices;
34 using System.Runtime.InteropServices;
35 using System.Runtime.Serialization;
36 using System.Security;
37
38 namespace System.Reflection {
39         
40         internal struct MonoPropertyInfo {
41                 public Type parent;
42                 public String name;
43                 public MethodInfo get_method;
44                 public MethodInfo set_method;
45                 public PropertyAttributes attrs;
46                 
47                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
48                 internal static extern void get_property_info (MonoProperty prop, out MonoPropertyInfo info,
49                                                                PInfo req_info);
50
51                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
52                 internal static extern Type[] GetTypeModifiers (MonoProperty prop, bool optional);
53
54         }
55
56         [Flags]
57         internal enum PInfo {
58                 Attributes = 1,
59                 GetMethod  = 1 << 1,
60                 SetMethod  = 1 << 2,
61                 ReflectedType = 1 << 3,
62                 DeclaringType = 1 << 4,
63                 Name = 1 << 5
64                 
65         }
66
67         [Serializable]
68         internal class MonoProperty : PropertyInfo, ISerializable {
69 #pragma warning disable 649
70                 internal IntPtr klass;
71                 internal IntPtr prop;
72                 MonoPropertyInfo info;
73                 PInfo cached;
74 #pragma warning restore 649
75                 
76                 public override PropertyAttributes Attributes {
77                         get {
78                                 MonoPropertyInfo info;
79                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.Attributes);
80                                 return info.attrs;
81                         }
82                 }
83                 
84                 public override bool CanRead {
85                         get {
86                                 MonoPropertyInfo info;
87                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
88                                 return (info.get_method != null);
89                         }
90                 }
91                 
92                 public override bool CanWrite {
93                         get {
94                                 MonoPropertyInfo info;
95                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.SetMethod);
96                                 return (info.set_method != null);
97                         }
98                 }
99
100                 public override Type PropertyType {
101                         get {
102                                 if ((cached & (PInfo.GetMethod | PInfo.SetMethod)) != (PInfo.GetMethod | PInfo.SetMethod)) {
103                                         MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod | PInfo.SetMethod);
104                                         cached |= (PInfo.GetMethod | PInfo.SetMethod);
105                                 }
106
107                                 if (info.get_method != null) {
108                                         return info.get_method.ReturnType;
109                                 } else {
110                                         ParameterInfo[] parameters = info.set_method.GetParameters ();
111                                         
112                                         return parameters [parameters.Length - 1].ParameterType;
113                                 }
114                         }
115                 }
116
117                 public override Type ReflectedType {
118                         get {
119                                 MonoPropertyInfo info;
120                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.ReflectedType);
121                                 return info.parent;
122                         }
123                 }
124                 
125                 public override Type DeclaringType {
126                         get {
127                                 if ((cached & PInfo.DeclaringType) == 0) {
128                                         MonoPropertyInfo.get_property_info (this, out info, PInfo.DeclaringType);
129                                         cached |= PInfo.DeclaringType;
130                                 }
131                                 return info.parent;
132                         }
133                 }
134                 
135                 public override string Name {
136                         get {
137                                 if ((cached & PInfo.Name) == 0) {
138                                         MonoPropertyInfo.get_property_info (this, out info, PInfo.Name);
139                                         cached |= PInfo.Name;
140                                 }
141                                 return info.name;
142                         }
143                 }
144
145                 public override MethodInfo[] GetAccessors (bool nonPublic)
146                 {
147                         MonoPropertyInfo info;
148                         int nget = 0;
149                         int nset = 0;
150                         
151                         MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod | PInfo.SetMethod);
152                         if (info.set_method != null && (nonPublic || info.set_method.IsPublic))
153                                 nset = 1;
154                         if (info.get_method != null && (nonPublic || info.get_method.IsPublic))
155                                 nget = 1;
156
157                         MethodInfo[] res = new MethodInfo [nget + nset];
158                         int n = 0;
159                         if (nset != 0)
160                                 res [n++] = info.set_method;
161                         if (nget != 0)
162                                 res [n++] = info.get_method;
163                         return res;
164                 }
165
166                 public override MethodInfo GetGetMethod (bool nonPublic)
167                 {
168                         if ((cached & PInfo.GetMethod) == 0) {
169                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
170                                 cached |= PInfo.GetMethod;
171                         }
172                         if (info.get_method != null && (nonPublic || info.get_method.IsPublic))
173                                 return info.get_method;
174                         else
175                                 return null;
176                 }
177
178                 public override ParameterInfo[] GetIndexParameters()
179                 {
180                         MonoPropertyInfo info;
181                         MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
182                         if (info.get_method != null)
183                                 return info.get_method.GetParameters ();
184                         return new ParameterInfo [0];
185                 }
186                 
187                 public override MethodInfo GetSetMethod (bool nonPublic)
188                 {
189                         if ((cached & PInfo.SetMethod) == 0) {
190                                 MonoPropertyInfo.get_property_info (this, out info, PInfo.SetMethod);
191                                 cached |= PInfo.SetMethod;
192                         }
193                         if (info.set_method != null && (nonPublic || info.set_method.IsPublic))
194                                 return info.set_method;
195                         else
196                                 return null;
197                 }
198
199                 // According to MSDN the inherit parameter is ignored here and
200                 // the behavior always defaults to inherit = false
201                 //
202                 public override bool IsDefined (Type attributeType, bool inherit)
203                 {
204                         return MonoCustomAttrs.IsDefined (this, attributeType, false);
205                 }
206
207                 public override object[] GetCustomAttributes (bool inherit)
208                 {
209                         return MonoCustomAttrs.GetCustomAttributes (this, false);
210                 }
211                 
212                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
213                 {
214                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, false);
215                 }
216
217                 public override object GetValue (object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
218                 {
219                         object ret = null;
220
221                         MethodInfo method = GetGetMethod (true);
222                         if (method == null)
223                                 throw new ArgumentException ("Get Method not found for '" + Name + "'");
224
225                         try {
226                                 if (index == null || index.Length == 0) 
227                                         ret = method.Invoke (obj, invokeAttr, binder, null, culture);
228                                 else
229                                         ret = method.Invoke (obj, invokeAttr, binder, index, culture);
230                         }
231                         catch (SecurityException se) {
232                                 throw new TargetInvocationException (se);
233                         }
234
235                         return ret;
236                 }
237
238                 public override void SetValue (object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
239                 {
240                         MethodInfo method = GetSetMethod (true);
241                         if (method == null)
242                                 throw new ArgumentException ("Set Method not found for '" + Name + "'");
243                         
244                         object [] parms;
245                         if (index == null || index.Length == 0) 
246                                 parms = new object [] {value};
247                         else {
248                                 int ilen = index.Length;
249                                 parms = new object [ilen+ 1];
250                                 index.CopyTo (parms, 0);
251                                 parms [ilen] = value;
252                         }
253
254                         method.Invoke (obj, invokeAttr, binder, parms, culture);
255                 }
256
257                 public override string ToString () {
258                         return PropertyType.ToString () + " " + Name;
259                 }
260
261 #if NET_2_0 || BOOTSTRAP_NET_2_0
262
263                 public override Type[] GetOptionalCustomModifiers () {
264                         Type[] types = MonoPropertyInfo.GetTypeModifiers (this, true);
265                         if (types == null)
266                                 return Type.EmptyTypes;
267                         return types;
268                 }
269
270                 public override Type[] GetRequiredCustomModifiers () {
271                         Type[] types = MonoPropertyInfo.GetTypeModifiers (this, false);
272                         if (types == null)
273                                 return Type.EmptyTypes;
274                         return types;
275                 }
276 #endif
277
278                 // ISerializable
279                 public void GetObjectData (SerializationInfo info, StreamingContext context) 
280                 {
281                         MemberInfoSerializationHolder.Serialize (info, Name, ReflectedType,
282                                 ToString(), MemberTypes.Property);
283                 }
284         }
285 }