2 // System.Reflection.Emit/MethodBuilder.cs
5 // Paolo Molaro (lupus@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Reflection
;
35 using System
.Reflection
.Emit
;
36 using System
.Globalization
;
37 using System
.Security
;
38 using System
.Security
.Permissions
;
39 using System
.Runtime
.CompilerServices
;
40 using System
.Runtime
.InteropServices
;
41 using System
.Diagnostics
.SymbolStore
;
43 namespace System
.Reflection
.Emit
46 [ComDefaultInterface (typeof (_MethodBuilder
))]
47 [ClassInterface (ClassInterfaceType
.None
)]
48 public sealed class MethodBuilder
: MethodInfo
, _MethodBuilder
50 #pragma warning disable 169, 414
51 private RuntimeMethodHandle mhandle
;
53 internal Type
[] parameters
;
54 private MethodAttributes attrs
; /* It's used directly by MCS */
55 private MethodImplAttributes iattrs
;
57 private int table_idx
;
59 private ILGenerator ilgen
;
60 private TypeBuilder type
;
61 internal ParameterBuilder
[] pinfo
;
62 private CustomAttributeBuilder
[] cattrs
;
63 private MethodInfo override_method
;
64 private string pi_dll
;
65 private string pi_entry
;
66 private CharSet charset
;
67 private uint extra_flags
; /* this encodes set_last_error etc */
68 private CallingConvention native_cc
;
69 private CallingConventions call_conv
;
70 private bool init_locals
= true;
71 private IntPtr generic_container
;
72 internal GenericTypeParameterBuilder
[] generic_params
;
73 private Type
[] returnModReq
;
74 private Type
[] returnModOpt
;
75 private Type
[][] paramModReq
;
76 private Type
[][] paramModOpt
;
77 private RefEmitPermissionSet
[] permissions
;
78 #pragma warning restore 169, 414
80 internal MethodBuilder (TypeBuilder tb
, string name
, MethodAttributes attributes
, CallingConventions callingConvention
, Type returnType
, Type
[] returnModReq
, Type
[] returnModOpt
, Type
[] parameterTypes
, Type
[][] paramModReq
, Type
[][] paramModOpt
)
83 this.attrs
= attributes
;
84 this.call_conv
= callingConvention
;
85 this.rtype
= returnType
;
86 this.returnModReq
= returnModReq
;
87 this.returnModOpt
= returnModOpt
;
88 this.paramModReq
= paramModReq
;
89 this.paramModOpt
= paramModOpt
;
90 // The MSDN docs does not specify this, but the MS MethodBuilder
91 // appends a HasThis flag if the method is not static
92 if ((attributes
& MethodAttributes
.Static
) == 0)
93 this.call_conv
|= CallingConventions
.HasThis
;
94 if (parameterTypes
!= null) {
95 for (int i
= 0; i
< parameterTypes
.Length
; ++i
)
96 if (parameterTypes
[i
] == null)
97 throw new ArgumentException ("Elements of the parameterTypes array cannot be null", "parameterTypes");
99 this.parameters
= new Type
[parameterTypes
.Length
];
100 System
.Array
.Copy (parameterTypes
, this.parameters
, parameterTypes
.Length
);
103 table_idx
= get_next_table_index (this, 0x06, true);
105 ((ModuleBuilder
)tb
.Module
).RegisterToken (this, GetToken ().Token
);
108 internal MethodBuilder (TypeBuilder tb
, string name
, MethodAttributes attributes
,
109 CallingConventions callingConvention
, Type returnType
, Type
[] returnModReq
, Type
[] returnModOpt
, Type
[] parameterTypes
, Type
[][] paramModReq
, Type
[][] paramModOpt
,
110 String dllName
, String entryName
, CallingConvention nativeCConv
, CharSet nativeCharset
)
111 : this (tb
, name
, attributes
, callingConvention
, returnType
, returnModReq
, returnModOpt
, parameterTypes
, paramModReq
, paramModOpt
)
114 pi_entry
= entryName
;
115 native_cc
= nativeCConv
;
116 charset
= nativeCharset
;
119 public override bool ContainsGenericParameters
{
120 get { throw new NotSupportedException (); }
123 public bool InitLocals
{
124 get {return init_locals;}
125 set {init_locals = value;}
128 internal TypeBuilder TypeBuilder
{
132 public override RuntimeMethodHandle MethodHandle
{
134 throw NotSupported ();
138 public override Type ReturnType
{
139 get { return rtype; }
142 public override Type ReflectedType
{
146 public override Type DeclaringType
{
150 public override string Name
{
154 public override MethodAttributes Attributes
{
155 get { return attrs; }
158 public override ICustomAttributeProvider ReturnTypeCustomAttributes
{
162 public override CallingConventions CallingConvention
{
163 get { return call_conv; }
166 [MonoTODO("Not implemented")]
167 public string Signature
{
169 throw new NotImplementedException ();
174 internal bool BestFitMapping
{
176 extra_flags
= (uint) ((extra_flags
& ~
0x30) | (uint)(value ? 0x10 : 0x20));
181 internal bool ThrowOnUnmappableChar
{
183 extra_flags
= (uint) ((extra_flags
& ~
0x3000) | (uint)(value ? 0x1000 : 0x2000));
188 internal bool ExactSpelling
{
190 extra_flags
= (uint) ((extra_flags
& ~
0x01) | (uint)(value ? 0x01 : 0x00));
195 internal bool SetLastError
{
197 extra_flags
= (uint) ((extra_flags
& ~
0x40) | (uint)(value ? 0x40 : 0x00));
201 public MethodToken
GetToken()
203 return new MethodToken(0x06000000 | table_idx
);
206 public override MethodInfo
GetBaseDefinition()
211 public override MethodImplAttributes
GetMethodImplementationFlags()
216 public override ParameterInfo
[] GetParameters()
218 if (!type
.is_created
)
219 throw NotSupported ();
220 if (parameters
== null)
223 ParameterInfo
[] retval
= new ParameterInfo
[parameters
.Length
];
224 for (int i
= 0; i
< parameters
.Length
; i
++) {
225 retval
[i
] = new ParameterInfo (pinfo
== null ? null : pinfo
[i
+ 1], parameters
[i
], this, i
+ 1);
230 internal override int GetParameterCount ()
232 if (parameters
== null)
235 return parameters
.Length
;
238 public Module
GetModule ()
243 public void CreateMethodBody (byte[] il
, int count
)
245 if ((il
!= null) && ((count
< 0) || (count
> il
.Length
)))
246 throw new ArgumentOutOfRangeException ("Index was out of range. Must be non-negative and less than the size of the collection.");
248 if ((code
!= null) || type
.is_created
)
249 throw new InvalidOperationException ("Type definition of the method is complete.");
254 code
= new byte [count
];
255 System
.Array
.Copy(il
, code
, count
);
259 public override Object
Invoke(Object obj
, BindingFlags invokeAttr
, Binder binder
, Object
[] parameters
, CultureInfo culture
)
261 throw NotSupported ();
264 public override bool IsDefined (Type attributeType
, bool inherit
)
266 throw NotSupported ();
269 public override object[] GetCustomAttributes (bool inherit
)
272 * On MS.NET, this always returns not_supported, but we can't do this
273 * since there would be no way to obtain custom attributes of
274 * dynamically created ctors.
277 return MonoCustomAttrs
.GetCustomAttributes (this, inherit
);
279 throw NotSupported ();
282 public override object[] GetCustomAttributes (Type attributeType
, bool inherit
)
285 return MonoCustomAttrs
.GetCustomAttributes (this, attributeType
, inherit
);
287 throw NotSupported ();
290 public ILGenerator
GetILGenerator ()
292 return GetILGenerator (64);
295 public ILGenerator
GetILGenerator (int size
)
297 if (((iattrs
& MethodImplAttributes
.CodeTypeMask
) !=
298 MethodImplAttributes
.IL
) ||
299 ((iattrs
& MethodImplAttributes
.ManagedMask
) !=
300 MethodImplAttributes
.Managed
))
301 throw new InvalidOperationException ("Method body should not exist.");
304 ilgen
= new ILGenerator (type
.Module
, ((ModuleBuilder
)type
.Module
).GetTokenGenerator (), size
);
308 public ParameterBuilder
DefineParameter (int position
, ParameterAttributes attributes
, string strParamName
)
313 // Extension: Mono allows position == 0 for the return attribute
315 if ((position
< 0) || (position
> parameters
.Length
))
316 throw new ArgumentOutOfRangeException ("position");
318 ParameterBuilder pb
= new ParameterBuilder (this, position
, attributes
, strParamName
);
320 pinfo
= new ParameterBuilder
[parameters
.Length
+ 1];
321 pinfo
[position
] = pb
;
325 internal void check_override ()
327 if (override_method
!= null && override_method
.IsVirtual
&& !IsVirtual
)
328 throw new TypeLoadException (String
.Format("Method '{0}' override '{1}' but it is not virtual", name
, override_method
));
331 internal void fixup ()
333 if (((attrs
& (MethodAttributes
.Abstract
| MethodAttributes
.PinvokeImpl
)) == 0) && ((iattrs
& (MethodImplAttributes
.Runtime
| MethodImplAttributes
.InternalCall
)) == 0)) {
334 // do not allow zero length method body on MS.NET 2.0 (and higher)
335 if (((ilgen
== null) || (ilgen
.ILOffset
== 0)) && (code
== null || code
.Length
== 0))
336 throw new InvalidOperationException (
337 String
.Format ("Method '{0}.{1}' does not have a method body.",
338 DeclaringType
.FullName
, Name
));
341 ilgen
.label_fixup ();
344 internal void GenerateDebugInfo (ISymbolWriter symbolWriter
)
346 if (ilgen
!= null && ilgen
.HasDebugInfo
) {
347 SymbolToken token
= new SymbolToken (GetToken().Token
);
348 symbolWriter
.OpenMethod (token
);
349 symbolWriter
.SetSymAttribute (token
, "__name", System
.Text
.Encoding
.UTF8
.GetBytes (Name
));
350 ilgen
.GenerateDebugInfo (symbolWriter
);
351 symbolWriter
.CloseMethod ();
355 public void SetCustomAttribute (CustomAttributeBuilder customBuilder
)
357 if (customBuilder
== null)
358 throw new ArgumentNullException ("customBuilder");
360 switch (customBuilder
.Ctor
.ReflectedType
.FullName
) {
361 case "System.Runtime.CompilerServices.MethodImplAttribute":
362 byte[] data
= customBuilder
.Data
;
363 int impla
; // the (stupid) ctor takes a short or an int ...
364 impla
= (int)data
[2];
365 impla
|= ((int)data
[3]) << 8;
366 iattrs
|= (MethodImplAttributes
)impla
;
369 case "System.Runtime.InteropServices.DllImportAttribute":
370 CustomAttributeBuilder
.CustomAttributeInfo attr
= CustomAttributeBuilder
.decode_cattr (customBuilder
);
371 bool preserveSig
= true;
374 * It would be easier to construct a DllImportAttribute from
375 * the custom attribute builder, but the DllImportAttribute
376 * does not contain all the information required here, ie.
377 * - some parameters, like BestFitMapping has three values
378 * ("on", "off", "missing"), but DllImportAttribute only
379 * contains two (on/off).
380 * - PreserveSig is true by default, while it is false by
381 * default in DllImportAttribute.
384 pi_dll
= (string)attr
.ctorArgs
[0];
385 if (pi_dll
== null || pi_dll
.Length
== 0)
386 throw new ArgumentException ("DllName cannot be empty");
388 native_cc
= System
.Runtime
.InteropServices
.CallingConvention
.Winapi
;
390 for (int i
= 0; i
< attr
.namedParamNames
.Length
; ++i
) {
391 string name
= attr
.namedParamNames
[i
];
392 object value = attr
.namedParamValues
[i
];
394 if (name
== "CallingConvention")
395 native_cc
= (CallingConvention
)value;
396 else if (name
== "CharSet")
397 charset
= (CharSet
)value;
398 else if (name
== "EntryPoint")
399 pi_entry
= (string)value;
400 else if (name
== "ExactSpelling")
401 ExactSpelling
= (bool)value;
402 else if (name
== "SetLastError")
403 SetLastError
= (bool)value;
404 else if (name
== "PreserveSig")
405 preserveSig
= (bool)value;
406 else if (name
== "BestFitMapping")
407 BestFitMapping
= (bool)value;
408 else if (name
== "ThrowOnUnmappableChar")
409 ThrowOnUnmappableChar
= (bool)value;
412 attrs
|= MethodAttributes
.PinvokeImpl
;
414 iattrs
|= MethodImplAttributes
.PreserveSig
;
417 case "System.Runtime.InteropServices.PreserveSigAttribute":
418 iattrs
|= MethodImplAttributes
.PreserveSig
;
420 case "System.Runtime.CompilerServices.SpecialNameAttribute":
421 attrs
|= MethodAttributes
.SpecialName
;
423 case "System.Security.SuppressUnmanagedCodeSecurityAttribute":
424 attrs
|= MethodAttributes
.HasSecurity
;
428 if (cattrs
!= null) {
429 CustomAttributeBuilder
[] new_array
= new CustomAttributeBuilder
[cattrs
.Length
+ 1];
430 cattrs
.CopyTo (new_array
, 0);
431 new_array
[cattrs
.Length
] = customBuilder
;
434 cattrs
= new CustomAttributeBuilder
[1];
435 cattrs
[0] = customBuilder
;
440 public void SetCustomAttribute (ConstructorInfo con
, byte[] binaryAttribute
)
443 throw new ArgumentNullException ("con");
444 if (binaryAttribute
== null)
445 throw new ArgumentNullException ("binaryAttribute");
446 SetCustomAttribute (new CustomAttributeBuilder (con
, binaryAttribute
));
449 public void SetImplementationFlags (MethodImplAttributes attributes
)
455 public void AddDeclarativeSecurity (SecurityAction action
, PermissionSet pset
)
459 throw new ArgumentNullException ("pset");
460 if ((action
== SecurityAction
.RequestMinimum
) ||
461 (action
== SecurityAction
.RequestOptional
) ||
462 (action
== SecurityAction
.RequestRefuse
))
463 throw new ArgumentOutOfRangeException ("Request* values are not permitted", "action");
467 if (permissions
!= null) {
468 /* Check duplicate actions */
469 foreach (RefEmitPermissionSet
set in permissions
)
470 if (set.action
== action
)
471 throw new InvalidOperationException ("Multiple permission sets specified with the same SecurityAction.");
473 RefEmitPermissionSet
[] new_array
= new RefEmitPermissionSet
[permissions
.Length
+ 1];
474 permissions
.CopyTo (new_array
, 0);
475 permissions
= new_array
;
478 permissions
= new RefEmitPermissionSet
[1];
480 permissions
[permissions
.Length
- 1] = new RefEmitPermissionSet (action
, pset
.ToXml ().ToString ());
481 attrs
|= MethodAttributes
.HasSecurity
;
485 [Obsolete ("An alternate API is available: Emit the MarshalAs custom attribute instead.")]
486 public void SetMarshal (UnmanagedMarshal unmanagedMarshal
)
489 throw new NotImplementedException ();
493 public void SetSymCustomAttribute (string name
, byte[] data
)
496 throw new NotImplementedException ();
499 public override string ToString()
501 return "MethodBuilder [" + type
.Name
+ "::" + name
+ "]";
505 public override bool Equals (object obj
)
507 return base.Equals (obj
);
510 public override int GetHashCode ()
512 return name
.GetHashCode ();
515 internal override int get_next_table_index (object obj
, int table
, bool inc
)
517 return type
.get_next_table_index (obj
, table
, inc
);
520 internal void set_override (MethodInfo mdecl
)
522 override_method
= mdecl
;
525 private void RejectIfCreated ()
528 throw new InvalidOperationException ("Type definition of the method is complete.");
531 private Exception
NotSupported ()
533 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
536 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
537 public override extern MethodInfo
MakeGenericMethod (params Type
[] typeArguments
);
539 public override bool IsGenericMethodDefinition
{
541 return generic_params
!= null;
545 public override bool IsGenericMethod
{
547 return generic_params
!= null;
551 public override MethodInfo
GetGenericMethodDefinition ()
553 if (!IsGenericMethodDefinition
)
554 throw new InvalidOperationException ();
559 public override Type
[] GetGenericArguments ()
561 if (generic_params
== null)
562 return Type
.EmptyTypes
;
564 Type
[] result
= new Type
[generic_params
.Length
];
565 for (int i
= 0; i
< generic_params
.Length
; i
++)
566 result
[i
] = generic_params
[i
];
571 public GenericTypeParameterBuilder
[] DefineGenericParameters (params string[] names
)
574 throw new ArgumentNullException ("names");
575 if (names
.Length
== 0)
576 throw new ArgumentException ("names");
578 generic_params
= new GenericTypeParameterBuilder
[names
.Length
];
579 for (int i
= 0; i
< names
.Length
; i
++) {
580 string item
= names
[i
];
582 throw new ArgumentNullException ("names");
583 generic_params
[i
] = new GenericTypeParameterBuilder (type
, this, item
, i
);
586 return generic_params
;
589 public void SetReturnType (Type returnType
)
594 public void SetParameters (params Type
[] parameterTypes
)
596 if (parameterTypes
!= null) {
597 for (int i
= 0; i
< parameterTypes
.Length
; ++i
)
598 if (parameterTypes
[i
] == null)
599 throw new ArgumentException ("Elements of the parameterTypes array cannot be null", "parameterTypes");
601 this.parameters
= new Type
[parameterTypes
.Length
];
602 System
.Array
.Copy (parameterTypes
, this.parameters
, parameterTypes
.Length
);
606 public void SetSignature (Type returnType
, Type
[] returnTypeRequiredCustomModifiers
, Type
[] returnTypeOptionalCustomModifiers
, Type
[] parameterTypes
, Type
[][] parameterTypeRequiredCustomModifiers
, Type
[][] parameterTypeOptionalCustomModifiers
)
608 SetReturnType (returnType
);
609 SetParameters (parameterTypes
);
610 this.returnModReq
= returnTypeRequiredCustomModifiers
;
611 this.returnModOpt
= returnTypeOptionalCustomModifiers
;
612 this.paramModReq
= parameterTypeRequiredCustomModifiers
;
613 this.paramModOpt
= parameterTypeOptionalCustomModifiers
;
616 public override Module Module
{
622 void _MethodBuilder
.GetIDsOfNames([In
] ref Guid riid
, IntPtr rgszNames
, uint cNames
, uint lcid
, IntPtr rgDispId
)
624 throw new NotImplementedException ();
627 void _MethodBuilder
.GetTypeInfo (uint iTInfo
, uint lcid
, IntPtr ppTInfo
)
629 throw new NotImplementedException ();
632 void _MethodBuilder
.GetTypeInfoCount (out uint pcTInfo
)
634 throw new NotImplementedException ();
637 void _MethodBuilder
.Invoke (uint dispIdMember
, [In
] ref Guid riid
, uint lcid
, short wFlags
, IntPtr pDispParams
, IntPtr pVarResult
, IntPtr pExcepInfo
, IntPtr puArgErr
)
639 throw new NotImplementedException ();