2 // System.Reflection.Emit.DynamicMethod.cs
5 // Paolo Molaro (lupus@ximian.com)
6 // Zoltan Varga (vargaz@freemail.hu)
8 // (C) 2003 Ximian, Inc. http://www.ximian.com
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Reflection;
38 using System.Reflection.Emit;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
43 namespace System.Reflection.Emit {
46 [StructLayout (LayoutKind.Sequential)]
47 public sealed class DynamicMethod : MethodInfo {
49 #pragma warning disable 169, 414, 649
50 #region Sync with reflection.h
51 private RuntimeMethodHandle mhandle;
53 private Type returnType;
54 private Type[] parameters;
55 private MethodAttributes attributes;
56 private CallingConventions callingConvention;
57 private Module module;
58 private bool skipVisibility;
59 private bool init_locals = true;
60 private ILGenerator ilgen;
62 private object[] refs;
63 private IntPtr referenced_by;
66 #pragma warning restore 169, 414, 649
68 private Delegate deleg;
69 private MonoMethod method;
70 private ParameterBuilder[] pinfo;
71 internal bool creating;
72 private DynamicILInfo il_info;
74 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
77 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
80 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) {
83 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) {
86 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, owner, owner.Module, skipVisibility, false) {
89 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, null, m, skipVisibility, false) {
92 public DynamicMethod (string name, Type returnType, Type[] parameterTypes) : this (name, returnType, parameterTypes, false) {
95 [MonoTODO ("Visibility is not restricted")]
96 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)
97 : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, null, null, restrictedSkipVisibility, true)
101 DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type [] parameterTypes, Type owner, Module m, bool skipVisibility, bool anonHosted)
104 throw new ArgumentNullException ("name");
105 if (returnType == null)
106 returnType = typeof (void);
107 if ((m == null) && !anonHosted)
108 throw new ArgumentNullException ("m");
109 if (returnType.IsByRef)
110 throw new ArgumentException ("Return type can't be a byref type", "returnType");
111 if (parameterTypes != null) {
112 for (int i = 0; i < parameterTypes.Length; ++i)
113 if (parameterTypes [i] == null)
114 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
116 if (owner != null && (owner.IsArray || owner.IsInterface)) {
117 throw new ArgumentException ("Owner can't be an array or an interface.");
121 m = AnonHostModuleHolder.AnonHostModule;
124 this.attributes = attributes | MethodAttributes.Static;
125 this.callingConvention = callingConvention;
126 this.returnType = returnType;
127 this.parameters = parameterTypes;
130 this.skipVisibility = skipVisibility;
133 [MethodImplAttribute(MethodImplOptions.InternalCall)]
134 private extern void create_dynamic_method (DynamicMethod m);
136 private void CreateDynMethod () {
137 if (mhandle.Value == IntPtr.Zero) {
138 if (ilgen == null || ilgen.ILOffset == 0)
139 throw new InvalidOperationException ("Method '" + name + "' does not have a method body.");
141 ilgen.label_fixup (this);
143 // Have to create all DynamicMethods referenced by this one
145 // Used to avoid cycles
148 for (int i = 0; i < refs.Length; ++i) {
149 if (refs [i] is DynamicMethod) {
150 DynamicMethod m = (DynamicMethod)refs [i];
152 m.CreateDynMethod ();
160 create_dynamic_method (this);
168 public Delegate CreateDelegate (Type delegateType)
170 if (delegateType == null)
171 throw new ArgumentNullException ("delegateType");
177 deleg = Delegate.CreateDelegate (delegateType, this);
185 public Delegate CreateDelegate (Type delegateType, object target)
187 if (delegateType == null)
188 throw new ArgumentNullException ("delegateType");
192 /* Can't cache the delegate since it is different for each target */
193 return Delegate.CreateDelegate (delegateType, target, this);
196 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string parameterName)
199 // Extension: Mono allows position == 0 for the return attribute
201 if ((position < 0) || (position > parameters.Length))
202 throw new ArgumentOutOfRangeException ("position");
206 ParameterBuilder pb = new ParameterBuilder (this, position, attributes, parameterName);
208 pinfo = new ParameterBuilder [parameters.Length + 1];
209 pinfo [position] = pb;
213 public override MethodInfo GetBaseDefinition () {
217 [MonoTODO("Not implemented")]
218 public override object[] GetCustomAttributes (bool inherit) {
219 throw new NotImplementedException ();
222 [MonoTODO("Not implemented")]
223 public override object[] GetCustomAttributes (Type attributeType,
225 throw new NotImplementedException ();
228 public DynamicILInfo GetDynamicILInfo () {
230 il_info = new DynamicILInfo (this);
234 public ILGenerator GetILGenerator () {
235 return GetILGenerator (64);
238 public ILGenerator GetILGenerator (int streamSize) {
239 if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) !=
240 MethodImplAttributes.IL) ||
241 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) !=
242 MethodImplAttributes.Managed))
243 throw new InvalidOperationException ("Method body should not exist.");
246 ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), streamSize);
250 public override MethodImplAttributes GetMethodImplementationFlags () {
251 return MethodImplAttributes.IL | MethodImplAttributes.Managed;
254 public override ParameterInfo[] GetParameters ()
256 return GetParametersInternal ();
259 internal override ParameterInfo[] GetParametersInternal ()
261 if (parameters == null)
262 return EmptyArray<ParameterInfo>.Value;
264 ParameterInfo[] retval = new ParameterInfo [parameters.Length];
265 for (int i = 0; i < parameters.Length; i++) {
266 retval [i] = ParameterInfo.New (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
271 internal override int GetParametersCount ()
273 return parameters == null ? 0 : parameters.Length;
276 internal override Type GetParameterType (int pos) {
277 return parameters [pos];
281 public override object Invoke (object obj, object[] parameters) {
284 method = new MonoMethod (mhandle);
285 return method.Invoke (obj, parameters);
289 public override object Invoke (object obj, BindingFlags invokeAttr,
290 Binder binder, object[] parameters,
296 method = new MonoMethod (mhandle);
298 return method.Invoke (obj, parameters);
300 catch (MethodAccessException mae) {
301 throw new TargetInvocationException ("Method cannot be invoked.", mae);
305 [MonoTODO("Not implemented")]
306 public override bool IsDefined (Type attributeType, bool inherit) {
307 throw new NotImplementedException ();
310 public override string ToString () {
311 string parms = String.Empty;
312 ParameterInfo[] p = GetParametersInternal ();
313 for (int i = 0; i < p.Length; ++i) {
315 parms = parms + ", ";
316 parms = parms + p [i].ParameterType.Name;
318 return ReturnType.Name+" "+Name+"("+parms+")";
321 public override MethodAttributes Attributes {
327 public override CallingConventions CallingConvention {
329 return callingConvention;
333 public override Type DeclaringType {
339 public bool InitLocals {
348 public override RuntimeMethodHandle MethodHandle {
354 public override Module Module {
360 public override string Name {
366 public override Type ReflectedType {
372 [MonoTODO("Not implemented")]
373 public override ParameterInfo ReturnParameter {
375 throw new NotImplementedException ();
379 public override Type ReturnType {
385 [MonoTODO("Not implemented")]
386 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
388 throw new NotImplementedException ();
393 public override int MetadataToken {
400 private void RejectIfCreated () {
401 if (mhandle.Value != IntPtr.Zero)
402 throw new InvalidOperationException ("Type definition of the method is complete.");
405 internal int AddRef (object reference) {
407 refs = new object [4];
408 if (nrefs >= refs.Length - 1) {
409 object [] new_refs = new object [refs.Length * 2];
410 System.Array.Copy (refs, new_refs, refs.Length);
413 refs [nrefs] = reference;
414 /* Reserved by the runtime */
415 refs [nrefs + 1] = null;
420 // This class takes care of constructing the module in a thread safe manner
421 class AnonHostModuleHolder {
422 public static Module anon_host_module;
424 static AnonHostModuleHolder () {
425 AssemblyName aname = new AssemblyName ();
426 aname.Name = "Anonymously Hosted DynamicMethods Assembly";
427 AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Run);
429 anon_host_module = ab.GetManifestModule ();
432 public static Module AnonHostModule {
434 return anon_host_module;
440 internal class DynamicMethodTokenGenerator : TokenGenerator {
442 private DynamicMethod m;
444 public DynamicMethodTokenGenerator (DynamicMethod m) {
448 public int GetToken (string str) {
449 return m.AddRef (str);
452 public int GetToken (MethodBase method, Type[] opt_param_types) {
453 throw new InvalidOperationException ();
456 public int GetToken (MemberInfo member, bool create_open_instance) {
457 return m.AddRef (member);
460 public int GetToken (SignatureHelper helper) {
461 return m.AddRef (helper);