2 // Permission is hereby granted, free of charge, to any person obtaining
3 // a copy of this software and associated documentation files (the
4 // "Software"), to deal in the Software without restriction, including
5 // without limitation the rights to use, copy, modify, merge, publish,
6 // distribute, sublicense, and/or sell copies of the Software, and to
7 // permit persons to whom the Software is furnished to do so, subject to
8 // the following conditions:
10 // The above copyright notice and this permission notice shall be
11 // included in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 // Copyright (C) Lluis Sanchez Gual, 2004
26 using System.Collections;
28 using System.Reflection;
29 using System.Reflection.Emit;
31 namespace Mono.CodeGeneration
33 public class CodeMethod
35 MethodBase methodBase;
38 MethodAttributes attributes;
40 TypeBuilder typeBuilder;
41 Type[] parameterTypes;
42 ArrayList customAttributes = new ArrayList ();
45 internal static CodeMethod DefineMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
47 return new CodeMethod (cls, name, attributes, returnType, parameterTypes);
50 public static CodeMethod DefineConstructor (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)
52 return new CodeMethod (cls, attributes, parameterTypes);
55 internal CodeMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
58 this.typeBuilder = cls.TypeBuilder;
60 this.attributes = attributes;
61 this.returnType = returnType;
62 this.parameterTypes = parameterTypes;
64 methodBase = typeBuilder.DefineMethod (name, attributes, returnType, parameterTypes);
65 builder = new CodeBuilder (cls);
68 CodeMethod (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)
71 this.typeBuilder = cls.TypeBuilder;
72 this.attributes = attributes;
73 this.parameterTypes = parameterTypes;
74 this.name = typeBuilder.Name;
76 methodBase = typeBuilder.DefineConstructor (attributes, CallingConventions.Standard, parameterTypes);
77 builder = new CodeBuilder (cls);
80 public TypeBuilder DeclaringType
82 get { return typeBuilder; }
85 public MethodInfo MethodInfo
87 get { return methodBase as MethodInfo; }
90 public MethodBase MethodBase
92 get { return methodBase; }
100 public MethodAttributes Attributes
102 get { return attributes; }
105 public Type ReturnType
107 get { return returnType; }
110 public Type[] ParameterTypes
112 get { return parameterTypes; }
115 public CodeBuilder CodeBuilder
117 get { return builder; }
122 get { return (attributes & MethodAttributes.Static) != 0; }
125 public CodeCustomAttribute CreateCustomAttribute (Type attributeType)
127 return CreateCustomAttribute (attributeType,
128 Type.EmptyTypes, new object [0]);
131 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs)
133 return CreateCustomAttribute (attributeType,
134 ctorArgTypes, ctorArgs, new string [0], new object [0]);
137 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues)
139 CodeCustomAttribute cca = CodeCustomAttribute.Create (
140 attributeType, ctorArgTypes, ctorArgs, namedArgFieldNames, namedArgValues);
141 SetCustomAttribute (cca);
145 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues)
147 CodeCustomAttribute cca = CodeCustomAttribute.Create (
148 attributeType, ctorArgTypes, ctorArgs, fields, fieldValues);
149 SetCustomAttribute (cca);
153 void SetCustomAttribute (CodeCustomAttribute cca)
155 if (methodBase is MethodBuilder)
156 ((MethodBuilder) methodBase).SetCustomAttribute (cca.Builder);
157 else if (methodBase is ConstructorBuilder)
158 ((ConstructorBuilder) methodBase).SetCustomAttribute (cca.Builder);
159 customAttributes.Add (cca);
162 public string PrintCode ()
164 StringWriter sw = new StringWriter ();
165 CodeWriter cw = new CodeWriter (sw);
167 return sw.ToString ();
170 public virtual void PrintCode (CodeWriter cp)
173 foreach (CodeCustomAttribute a in customAttributes)
175 if ((methodBase.Attributes & MethodAttributes.Static) != 0)
176 cp.Write ("static ");
177 if ((methodBase.Attributes & MethodAttributes.Public) != 0)
178 cp.Write ("public ");
179 if (returnType != null) cp.Write (returnType + " ");
180 cp.Write (name + " (");
181 for (int n=0; n<parameterTypes.Length; n++) {
182 if (n > 0) cp.Write (", ");
183 cp.Write (parameterTypes[n] + " arg" + n);
187 cp.WriteLineInd ("{");
189 builder.PrintCode (cp);
191 cp.WriteLineUnind ("}");
194 public CodeArgumentReference GetArg (int n)
196 if (n < 0 || n >= parameterTypes.Length)
197 throw new InvalidOperationException ("Invalid argument number");
199 int narg = IsStatic ? n : n + 1;
200 return new CodeArgumentReference (parameterTypes[n], narg, "arg" + n);
203 public CodeArgumentReference GetThis ()
206 throw new InvalidOperationException ("'this' not available in static methods");
208 return new CodeArgumentReference (DeclaringType, 0, "this");
211 public void Generate ()
213 ILGenerator gen = methodBase is MethodInfo ? ((MethodBuilder)methodBase).GetILGenerator() : ((ConstructorBuilder)methodBase).GetILGenerator();
214 Label returnLabel = gen.DefineLabel ();
215 builder.ReturnLabel = returnLabel;
216 builder.Generate (gen);
217 gen.MarkLabel(returnLabel);
218 gen.Emit(OpCodes.Ret);
221 public void UpdateMethodBase (Type type)
223 if (methodBase is MethodInfo)
224 methodBase = type.GetMethod (methodBase.Name, parameterTypes);
226 methodBase = type.GetConstructor (parameterTypes);