Merge pull request #201 from QuickJack/master
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodOnTypeBuilderInst.cs
1 //
2 // System.Reflection.Emit/MethodOnTypeBuilderInst.cs
3 //
4 // Author:
5 //   Zoltan Varga (vargaz@gmail.com)
6 //
7 //
8 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Globalization;
32 using System.Reflection;
33 using System.Text;
34
35 namespace System.Reflection.Emit
36 {
37         /*
38          * This class represents a method of an instantiation of a generic type builder.
39          */
40         internal class MethodOnTypeBuilderInst : MethodInfo
41         {
42                 #region Keep in sync with object-internals.h
43                 Type instantiation;
44                 MethodInfo base_method; /*This is the base method definition, it must be non-inflated and belong to a non-inflated type.*/
45                 Type[] method_arguments;
46                 #endregion
47                 MethodInfo generic_method_definition;
48
49                 public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodInfo base_method)
50                 {
51                         this.instantiation = instantiation;
52                         this.base_method = base_method;
53                 }
54
55                 internal MethodOnTypeBuilderInst (MethodOnTypeBuilderInst gmd, Type[] typeArguments)
56                 {
57                         this.instantiation = gmd.instantiation;
58                         this.base_method = gmd.base_method;
59                         this.method_arguments = new Type [typeArguments.Length];
60                         typeArguments.CopyTo (this.method_arguments, 0);
61                         this.generic_method_definition = gmd;
62                 }
63
64                 internal MethodOnTypeBuilderInst (MethodInfo method, Type[] typeArguments)
65                 {
66                         this.instantiation = method.DeclaringType;
67                         this.base_method = ExtractBaseMethod (method);
68                         this.method_arguments = new Type [typeArguments.Length];
69                         typeArguments.CopyTo (this.method_arguments, 0);
70                         if (base_method != method)
71                                 this.generic_method_definition = method;
72                 }
73
74                 static MethodInfo ExtractBaseMethod (MethodInfo info)
75                 {
76                         if (info is MethodBuilder)
77                                 return info;
78                         if (info is MethodOnTypeBuilderInst)
79                                 return ((MethodOnTypeBuilderInst)info).base_method;
80
81                         if (info.IsGenericMethod)
82                                 info = info.GetGenericMethodDefinition ();
83
84                         Type t = info.DeclaringType;
85                         if (!t.IsGenericType || t.IsGenericTypeDefinition)
86                                 return info;
87
88                         return (MethodInfo)t.Module.ResolveMethod (info.MetadataToken);
89                 }
90
91                 internal Type[] GetTypeArgs ()
92                 {
93                         if (!instantiation.IsGenericType || instantiation.IsGenericParameter)
94                                 return null;                            
95
96                         return instantiation.GetGenericArguments ();
97                 }
98
99                 //
100                 // MemberInfo members
101                 //
102                 
103                 public override Type DeclaringType {
104                         get {
105                                 return instantiation;
106                         }
107                 }
108
109                 public override string Name {
110                         get {
111                                 return base_method.Name;
112                         }
113                 }
114
115                 public override Type ReflectedType {
116                         get {
117                                 return instantiation;
118                         }
119                 }
120
121                 public override Type ReturnType {
122                         get { 
123                                 return base_method.ReturnType;
124                         }
125                 }
126
127                 public override bool IsDefined (Type attributeType, bool inherit)
128                 {
129                         throw new NotSupportedException ();
130                 }
131
132                 public override object [] GetCustomAttributes (bool inherit)
133                 {
134                         throw new NotSupportedException ();
135                 }
136
137                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
138                 {
139                         throw new NotSupportedException ();
140                 }
141
142                 public override string ToString ()
143                 {
144                          //IEnumerable`1 get_Item(TKey)
145                          StringBuilder sb = new StringBuilder (ReturnType.ToString ());
146                          sb.Append (" ");
147                          sb.Append (base_method.Name);
148                          sb.Append ("(");
149                          sb.Append (")");
150                          return sb.ToString ();
151                 }
152                 //
153                 // MethodBase members
154                 //
155
156                 public override MethodImplAttributes GetMethodImplementationFlags ()
157                 {
158                         return base_method.GetMethodImplementationFlags ();
159                 }
160
161                 public override ParameterInfo [] GetParameters ()
162                 {
163                         throw new NotSupportedException ();
164                 }
165
166                 public override int MetadataToken {
167                         get {
168                                 return base.MetadataToken;
169                         }
170                 }
171
172                 internal override int GetParameterCount ()
173                 {
174                         return base_method.GetParameterCount ();
175                 }
176
177                 public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
178                 {
179                         throw new NotSupportedException ();
180                 }
181
182                 public override RuntimeMethodHandle MethodHandle {
183                         get {
184                                 throw new NotSupportedException ();
185                         }
186                 }
187
188                 public override MethodAttributes Attributes {
189                         get {
190                                 return base_method.Attributes;
191                         }
192                 }
193
194                 public override CallingConventions CallingConvention {
195                         get {
196                                 return base_method.CallingConvention;
197                         }
198                 }
199
200                 public override MethodInfo MakeGenericMethod (params Type [] methodInstantiation)
201                 {
202                         if (!base_method.IsGenericMethodDefinition || (method_arguments != null))
203                                 throw new InvalidOperationException ("Method is not a generic method definition");
204
205                         if (methodInstantiation == null)
206                                 throw new ArgumentNullException ("methodInstantiation");
207
208                         if (base_method.GetGenericArguments ().Length != methodInstantiation.Length)
209                                 throw new ArgumentException ("Incorrect length", "methodInstantiation");
210
211                         foreach (Type type in methodInstantiation) {
212                                 if (type == null)
213                                         throw new ArgumentNullException ("methodInstantiation");
214                         }
215
216                         return new MethodOnTypeBuilderInst (this, methodInstantiation);
217                 }
218
219                 public override Type [] GetGenericArguments ()
220                 {
221                         if (!base_method.IsGenericMethodDefinition)
222                                 return null;
223                         Type[] source = method_arguments ?? base_method.GetGenericArguments ();
224                         Type[] result = new Type [source.Length];
225                         source.CopyTo (result, 0);
226                         return result;
227                 }
228
229                 public override MethodInfo GetGenericMethodDefinition ()
230                 {
231                         return generic_method_definition ?? base_method;
232                 }
233
234                 public override bool ContainsGenericParameters {
235                         get {
236                                 if (base_method.ContainsGenericParameters)
237                                         return true;
238                                 if (!base_method.IsGenericMethodDefinition)
239                                         throw new NotSupportedException ();
240                                 if (method_arguments == null)
241                                         return true;
242                                 foreach (Type t in method_arguments) {
243                                         if (t.ContainsGenericParameters)
244                                                 return true;
245                                 }
246                                 return false;
247                         }
248                 }
249
250                 public override bool IsGenericMethodDefinition {
251                         get {
252                                 return base_method.IsGenericMethodDefinition && method_arguments == null;
253                         }
254                 }
255
256                 public override bool IsGenericMethod {
257                         get {
258                                 return base_method.IsGenericMethodDefinition;
259                         }
260                 }
261
262                 //
263                 // MethodInfo members
264                 //
265
266                 public override MethodInfo GetBaseDefinition ()
267                 {
268                         throw new NotSupportedException ();
269                 }
270
271                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
272                         get {
273                                 throw new NotSupportedException ();
274                         }
275                 }
276         }
277 }
278