2005-10-18 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System / System.ComponentModel.Design.Serialization / InstanceDescriptor.cs
1 //
2 // System.ComponentModel.Design.Serialization.InstanceDescriptor.cs
3 //
4 // Authors:
5 //   Martin Willemoes Hansen (mwh@sysrq.dk)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) 2003 Martin Willemoes Hansen
9 // (C) 2003 Andreas Nahr
10 // Copyright (C) 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.Collections;
33 using System.Reflection;
34 using System.Security.Permissions;
35
36 namespace System.ComponentModel.Design.Serialization {
37
38         [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
39         public sealed class InstanceDescriptor {
40
41                 private MemberInfo member;
42                 private ICollection arguments;
43                 private bool isComplete;
44
45                 public InstanceDescriptor (MemberInfo member, ICollection arguments)
46                         : this (member, arguments, true)
47                 {
48                 }
49
50                 public InstanceDescriptor(MemberInfo member, ICollection arguments, bool isComplete)
51                 {
52                         this.isComplete = isComplete;
53                         if ((member != null) && !IsMemberValid (member, arguments))
54                                 throw new ArgumentException ("Only Constructor, Method, Field or Property members allowed", "member");
55                         this.member = member;
56                         this.arguments = arguments;
57                 }
58
59                 private bool IsMemberValid (MemberInfo member, ICollection arguments)
60                 {
61                         switch (member.MemberType) {
62                         // According to docs only these types are allowed
63                         case MemberTypes.Constructor:
64                                 ConstructorInfo CI = (ConstructorInfo) member;
65                                 if (arguments == null) // null counts as no arguments
66                                         if (CI.GetParameters().Length != 0)
67                                                 throw new ArgumentException ("Invalid number of arguments for this constructor", "arguments");
68                                 if (arguments.Count != CI.GetParameters().Length)
69                                         throw new ArgumentException ("Invalid number of arguments for this constructor", "arguments");
70                                 return true;
71                         case MemberTypes.Method:
72                                 MethodInfo MI = (MethodInfo) member;
73                                 if (!MI.IsStatic)
74                                         throw new ArgumentException ("InstanceDescriptor only describes static (VB.Net: shared) members", "member");
75                                 if (arguments == null) // null counts as no arguments
76                                         if (MI.GetParameters().Length != 0)
77                                                 throw new ArgumentException ("Invalid number of arguments for this method", "arguments");
78                                 if (arguments.Count != MI.GetParameters().Length)
79                                         throw new ArgumentException ("Invalid number of arguments for this method", "arguments");
80                                 return true;
81                         case MemberTypes.Field:
82                                 FieldInfo FI = (FieldInfo) member;
83                                 if (!FI.IsStatic)
84                                         throw new ArgumentException ("InstanceDescriptor only describes static (VB.Net: shared) members", "member");
85                                 if (arguments == null) // null counts as no arguments
86                                         return true;
87                                 if (arguments.Count == 0)
88                                         throw new ArgumentException ("Field members do not take any arguments", "arguments");
89                                 return true;
90                         case MemberTypes.Property:
91                                 PropertyInfo PI = (PropertyInfo) member;
92                                 if (!(PI.CanRead))
93                                         throw new ArgumentException ("That property cannot be read", "member");
94                                 MethodInfo PIM = PI.GetGetMethod();
95                                 if (!PIM.IsStatic)
96                                         throw new ArgumentException ("InstanceDescriptor only describes static (VB.Net: shared) members", "member");
97                                 if (arguments == null) // null counts as no arguments
98                                         if (PIM.GetParameters().Length != 0)
99                                                 throw new ArgumentException ("Invalid number of arguments for this property", "arguments");
100                                 if (arguments.Count != PIM.GetParameters().Length)
101                                         throw new ArgumentException ("Invalid number of arguments for this property", "arguments");
102                                 return true;
103                         }
104                         return false;
105                 }
106
107                 public ICollection Arguments {
108                         get { 
109                                 // It seems MS does not return null even if we specified null as parameter (but does not cause an exception)
110                                 if (arguments == null)
111                                         return new object[0];
112                                 return arguments;
113                         }
114                 }
115
116                 public bool IsComplete {
117                         get { return isComplete; }
118                 }
119
120                 public MemberInfo MemberInfo {
121                         get { return member; }
122                 }
123
124                 private bool HasThis ()
125                 {
126                         if (member is ConstructorInfo)
127                                 return false;
128                         MethodInfo mi = (member as MethodInfo);
129                         if (mi != null)
130                                 return !mi.IsStatic;
131                         FieldInfo fi = (member as FieldInfo);
132                         if (fi != null)
133                                 return !fi.IsStatic;
134                         PropertyInfo pi = (member as PropertyInfo);
135                         if (pi != null)
136                                 return !pi.GetGetMethod ().IsStatic;
137                         return true;
138                 }
139
140                 public object Invoke()
141                 {
142                         object[] parsearguments;
143                         if (arguments == null)
144                                 parsearguments = new object[0];
145                         else if (HasThis ()) {
146                                 parsearguments = new object[arguments.Count - 1];
147                                 arguments.CopyTo (parsearguments, 0);
148                         } else {
149                                 parsearguments = (arguments as object[]);
150                                 if (parsearguments == null) {
151                                         parsearguments = new object[arguments.Count];
152                                         arguments.CopyTo (parsearguments, 0);
153                                 }
154                         }
155
156                         //MemberInfo member;
157                         switch (member.MemberType) {
158                         case MemberTypes.Constructor:
159                                 ConstructorInfo CI = (ConstructorInfo) member;
160                                 return CI.Invoke (parsearguments);
161
162                         case MemberTypes.Method:
163                                 MethodInfo MI = (MethodInfo) member;
164                                 return MI.Invoke (null, parsearguments);
165
166                         case MemberTypes.Field:
167                                 FieldInfo FI = (FieldInfo) member;
168                                 return FI.GetValue (null);
169
170                         case MemberTypes.Property:
171                                 PropertyInfo PI = (PropertyInfo) member;
172                                 return PI.GetValue (null, parsearguments);
173                         }
174                         return null;
175                 }
176         }
177 }