2 // MethodBuilderTest.cs - NUnit Test Cases for the MethodBuilder class
4 // Zoltan Varga (vargaz@freemail.hu)
6 // (C) Ximian, Inc. http://www.ximian.com
9 // - implement 'Signature' (what the hell it does???) and test it
10 // - implement Equals and test it
13 using System.Threading;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Runtime.InteropServices;
21 using NUnit.Framework;
23 namespace MonoTests.System.Reflection.Emit
26 public class MethodBuilderTest
28 private TypeBuilder genClass;
29 private ModuleBuilder module;
32 protected void SetUp ()
34 AssemblyName assemblyName = new AssemblyName ();
35 assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodBuilderTest";
37 AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
38 assemblyName, AssemblyBuilderAccess.Run);
39 module = assembly.DefineDynamicModule ("module1");
40 genClass = module.DefineType (genTypeName (), TypeAttributes.Public);
43 static int methodIndexer = 0;
44 static int typeIndexer = 0;
46 // Return a unique method name
47 private string genMethodName ()
49 return "m" + (methodIndexer++);
52 // Return a unique type name
53 private string genTypeName ()
55 return "class" + (typeIndexer++);
59 public void TestAttributes ()
61 MethodBuilder mb = genClass.DefineMethod (
62 genMethodName (), MethodAttributes.Public, typeof (void), new Type [0]);
63 Assert.AreEqual (MethodAttributes.Public, mb.Attributes);
67 public void TestCallingConvention ()
69 MethodBuilder mb = genClass.DefineMethod (
70 genMethodName (), 0, typeof (void), new Type [0]);
71 Assert.AreEqual (CallingConventions.Standard | CallingConventions.HasThis,
72 mb.CallingConvention, "CallingConvetion defaults to Standard+HasThis");
74 MethodBuilder mb3 = genClass.DefineMethod (
75 genMethodName (), 0, CallingConventions.VarArgs, typeof (void), new Type [0]);
76 Assert.AreEqual (CallingConventions.VarArgs | CallingConventions.HasThis,
77 mb3.CallingConvention, "CallingConvetion works");
79 MethodBuilder mb4 = genClass.DefineMethod (
80 genMethodName (), MethodAttributes.Static, CallingConventions.Standard,
81 typeof (void), new Type [0]);
82 Assert.AreEqual (CallingConventions.Standard, mb4.CallingConvention,
83 "Static implies !HasThis");
87 public void TestDeclaringType ()
89 MethodBuilder mb = genClass.DefineMethod (
90 genMethodName (), 0, typeof (void), new Type [0]);
92 Assert.AreEqual (genClass, mb.DeclaringType, "DeclaringType works");
96 public void TestInitLocals ()
98 MethodBuilder mb = genClass.DefineMethod (
99 genMethodName (), 0, typeof (void), new Type [0]);
101 Assert.IsTrue (mb.InitLocals, "#1");
102 mb.InitLocals = false;
103 Assert.IsFalse (mb.InitLocals, "#2");
107 [ExpectedException (typeof (NotSupportedException))]
108 public void TestMethodHandleIncomplete ()
110 MethodBuilder mb = genClass.DefineMethod (
111 genMethodName (), 0, typeof (void), new Type [0]);
113 RuntimeMethodHandle handle = mb.MethodHandle;
117 [ExpectedException (typeof (NotSupportedException))]
118 public void TestMethodHandleComplete ()
120 MethodBuilder mb = genClass.DefineMethod (
121 genMethodName (), 0, typeof (void), new Type [0]);
122 mb.CreateMethodBody (new byte [2], 1);
123 genClass.CreateType ();
125 RuntimeMethodHandle handle = mb.MethodHandle;
129 public void TestName ()
131 string name = genMethodName ();
132 MethodBuilder mb = genClass.DefineMethod (
133 name, 0, typeof (void), new Type [0]);
135 Assert.AreEqual (name, mb.Name);
139 public void TestReflectedType ()
141 MethodBuilder mb = genClass.DefineMethod (
142 genMethodName (), 0, typeof (void), new Type [0]);
144 Assert.AreEqual (genClass, mb.ReflectedType);
148 public void TestReturnType ()
150 MethodBuilder mb = genClass.DefineMethod (
151 genMethodName (), 0, typeof (Console), new Type [0]);
152 Assert.AreEqual (typeof (Console), mb.ReturnType, "#1");
154 MethodBuilder mb2 = genClass.DefineMethod (
155 genMethodName (), 0, null, new Type [0]);
156 Assert.IsTrue (mb2.ReturnType == null || mb2.ReturnType == typeof (void), "#2");
160 public void TestReturnTypeCustomAttributes ()
162 MethodBuilder mb = genClass.DefineMethod (
163 genMethodName (), 0, typeof (Console), new Type [0]);
164 Assert.IsNull (mb.ReturnTypeCustomAttributes);
168 public void TestSignature () {
169 MethodBuilder mb = genClass.DefineMethod (
170 "m91", 0, typeof (Console), new Type [1] { typeof (Console) });
172 Console.WriteLine (mb.Signature);
177 public void TestCreateMethodBody ()
179 MethodBuilder mb = genClass.DefineMethod (
180 genMethodName (), 0, typeof (void), new Type [0]);
183 mb.CreateMethodBody (null, 999);
185 // Check arguments 1.
187 mb.CreateMethodBody (new byte [1], -1);
189 } catch (ArgumentOutOfRangeException) {
192 // Check arguments 2.
194 mb.CreateMethodBody (new byte [1], 2);
196 } catch (ArgumentOutOfRangeException) {
199 mb.CreateMethodBody (new byte [2], 1);
201 // Could only be called once
203 mb.CreateMethodBody (new byte [2], 1);
205 } catch (InvalidOperationException) {
208 // Can not be called on a created type
209 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
210 MethodBuilder mb2 = tb.DefineMethod (
211 genMethodName (), 0, typeof (void), new Type [0]);
212 ILGenerator ilgen = mb2.GetILGenerator ();
213 ilgen.Emit (OpCodes.Ret);
217 mb2.CreateMethodBody (new byte [2], 1);
219 } catch (InvalidOperationException) {
224 [ExpectedException (typeof (InvalidOperationException))]
225 public void TestDefineParameterInvalidIndexComplete ()
227 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
228 MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
229 new Type [2] { typeof(int), typeof(int) });
230 mb.CreateMethodBody (new byte [2], 1);
232 mb.DefineParameter (-5, ParameterAttributes.None, "param1");
236 [ExpectedException (typeof (InvalidOperationException))]
237 public void TestDefineParameterValidIndexComplete ()
239 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
240 MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
241 new Type [2] { typeof(int), typeof(int) });
242 mb.CreateMethodBody (new byte [2], 1);
244 mb.DefineParameter (1, ParameterAttributes.None, "param1");
248 public void TestDefineParameter ()
250 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
251 MethodBuilder mb = tb.DefineMethod (
252 genMethodName (), 0, typeof (void),
253 new Type [2] { typeof (int), typeof (int) });
255 // index out of range
257 // This fails on mono because the mono version accepts a 0 index
260 mb.DefineParameter (0, 0, "param1");
262 } catch (ArgumentOutOfRangeException) {
267 mb.DefineParameter (3, 0, "param1");
269 } catch (ArgumentOutOfRangeException) {
273 mb.DefineParameter (1, 0, "param1");
274 mb.DefineParameter (1, 0, "param1");
275 mb.DefineParameter (2, 0, null);
277 mb.CreateMethodBody (new byte [2], 1);
280 mb.DefineParameter (1, 0, "param1");
282 } catch (InvalidOperationException) {
287 // MS.NET 2.x no longer allows a zero length method body
289 [ExpectedException (typeof (InvalidOperationException))]
290 public void ZeroLengthBodyTest1 ()
292 MethodBuilder mb = genClass.DefineMethod (
293 genMethodName (), 0, typeof (void),
294 new Type [2] { typeof (int), typeof (int) });
295 mb.CreateMethodBody (new byte [2], 0);
296 genClass.CreateType ();
299 // A zero length method body can be created
301 public void ZeroLengthBodyTest2 ()
303 MethodBuilder mb = genClass.DefineMethod (
304 genMethodName (), 0, typeof (void),
305 new Type [2] { typeof (int), typeof (int) });
306 mb.CreateMethodBody (new byte [2], 0);
310 public void TestHashCode ()
312 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
313 string methodName = genMethodName ();
314 MethodBuilder mb = tb.DefineMethod (methodName, 0, typeof (void),
315 new Type [2] { typeof(int), typeof(int) });
316 Assert.AreEqual (methodName.GetHashCode (), mb.GetHashCode ());
320 public void TestGetBaseDefinition ()
322 MethodBuilder mb = genClass.DefineMethod (
323 genMethodName (), 0, typeof (void), new Type [0]);
324 Assert.AreEqual (mb.GetBaseDefinition (), mb);
328 public void TestGetILGenerator ()
330 MethodBuilder mb = genClass.DefineMethod (
331 genMethodName (), 0, typeof (void), new Type [0]);
333 // The same instance is returned on the second call
334 ILGenerator ilgen1 = mb.GetILGenerator ();
335 ILGenerator ilgen2 = mb.GetILGenerator ();
337 Assert.AreEqual (ilgen1, ilgen2, "#1");
339 // Does not work on unmanaged code
340 MethodBuilder mb2 = genClass.DefineMethod (
341 genMethodName (), 0, typeof (void), new Type [0]);
343 mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);
344 mb2.GetILGenerator ();
346 } catch (InvalidOperationException) {
349 mb2.SetImplementationFlags (MethodImplAttributes.Native);
350 mb2.GetILGenerator ();
352 } catch (InvalidOperationException) {
357 public void TestMethodImplementationFlags ()
359 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
360 MethodBuilder mb = tb.DefineMethod (
361 genMethodName (), 0, typeof (void), new Type [0]);
363 Assert.AreEqual (MethodImplAttributes.Managed | MethodImplAttributes.IL,
364 mb.GetMethodImplementationFlags (), "#1");
366 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
368 Assert.AreEqual (MethodImplAttributes.OPTIL, mb.GetMethodImplementationFlags (), "#2");
370 mb.CreateMethodBody (new byte [2], 1);
371 mb.SetImplementationFlags (MethodImplAttributes.Managed);
374 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
376 } catch (InvalidOperationException) {
381 public void TestGetModule ()
383 MethodBuilder mb = genClass.DefineMethod (
384 genMethodName (), 0, typeof (void), new Type [0]);
385 Assert.AreEqual (module, mb.GetModule ());
389 public void TestGetParameters ()
391 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
392 MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
393 new Type [1] { typeof (void) });
396 * According to the MSDN docs, this method should fail with a
397 * NotSupportedException. In reality, it throws an
398 * InvalidOperationException under MS .NET, and returns the
399 * requested data under mono.
405 } catch (InvalidOperationException ex) {
406 Console.WriteLine (ex);
412 public void TestGetToken ()
414 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
415 MethodBuilder mb = tb.DefineMethod (
416 genMethodName (), 0, typeof (void), new Type [1] { typeof (void) });
421 public void TestInvoke ()
423 MethodBuilder mb = genClass.DefineMethod (
424 genMethodName (), 0, typeof (void),
425 new Type [1] { typeof (int) });
428 mb.Invoke (null, new object [1] { 42 });
430 } catch (NotSupportedException) {
434 mb.Invoke (null, 0, null, new object [1] { 42 }, null);
436 } catch (NotSupportedException) {
441 [ExpectedException (typeof (NotSupportedException))]
442 public void TestIsDefined ()
444 MethodBuilder mb = genClass.DefineMethod (
445 genMethodName (), 0, typeof (void),
446 new Type [1] { typeof (int) });
447 mb.IsDefined (null, true);
451 public void TestGetCustomAttributes_Incomplete ()
453 MethodBuilder mb = genClass.DefineMethod (
454 genMethodName (), 0, typeof (void),
455 new Type [1] { typeof (int) });
458 mb.GetCustomAttributes (true);
460 } catch (NotSupportedException) {
464 mb.GetCustomAttributes (null, true);
466 } catch (NotSupportedException) {
471 [Category ("NotWorking")]
472 public void TestGetCustomAttributes_Complete ()
474 MethodBuilder mb = genClass.DefineMethod (
475 genMethodName (), 0, typeof (void),
476 new Type [1] { typeof (int) });
477 mb.GetILGenerator ().Emit (OpCodes.Ret);
478 genClass.CreateType ();
481 mb.GetCustomAttributes (true);
483 } catch (NotSupportedException) {
487 mb.GetCustomAttributes (null, true);
489 } catch (NotSupportedException) {
494 public void TestSetCustomAttribute ()
496 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
497 string name = genMethodName ();
498 MethodBuilder mb = tb.DefineMethod (
499 name, MethodAttributes.Public, typeof (void),
500 new Type [1] { typeof (int) });
504 mb.SetCustomAttribute (null);
506 } catch (ArgumentNullException) {
509 byte [] custAttrData = { 1, 0, 0, 0, 0 };
510 Type attrType = Type.GetType
511 ("System.Reflection.AssemblyKeyNameAttribute");
512 Type [] paramTypes = new Type [1];
513 paramTypes [0] = typeof (String);
514 ConstructorInfo ctorInfo =
515 attrType.GetConstructor (paramTypes);
517 mb.SetCustomAttribute (ctorInfo, custAttrData);
519 // Test MethodImplAttribute
520 mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute).GetConstructor (new Type [1] { typeof (short) }), new object [1] { (short) MethodImplAttributes.Synchronized }));
521 mb.GetILGenerator ().Emit (OpCodes.Ret);
523 Type t = tb.CreateType ();
525 Assert.AreEqual (t.GetMethod (name).GetMethodImplementationFlags (),
526 MethodImplAttributes.Synchronized, "#2");
528 // Null arguments again
530 mb.SetCustomAttribute (null, new byte [2]);
532 } catch (ArgumentNullException) {
536 mb.SetCustomAttribute (ctorInfo, null);
538 } catch (ArgumentNullException) {
543 public void SetCustomAttribute_DllImport_DllName_Empty ()
545 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
546 MethodBuilder mb = tb.DefineMethod (genMethodName (),
547 MethodAttributes.Public, typeof (void),
548 new Type [1] { typeof (int) });
550 ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
551 new Type [] { typeof (string) });
553 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
554 new object [] { string.Empty }));
556 } catch (ArgumentException ex) {
557 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
558 Assert.IsNull (ex.InnerException, "#3");
559 Assert.IsNotNull (ex.Message, "#4");
560 Assert.IsNull (ex.ParamName, "#5");
565 public void SetCustomAttribute_DllImport_DllName_Null ()
567 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
568 MethodBuilder mb = tb.DefineMethod (genMethodName (),
569 MethodAttributes.Public, typeof (void),
570 new Type [1] { typeof (int) });
572 ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
573 new Type [] { typeof (string) });
575 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
576 new object [] { null }));
578 } catch (ArgumentException ex) {
579 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
580 Assert.IsNull (ex.InnerException, "#3");
581 Assert.IsNotNull (ex.Message, "#4");
582 Assert.IsNull (ex.ParamName, "#5");
587 public void SetCustomAttribute_SuppressUnmanagedCodeSecurity ()
589 string mname = genMethodName ();
591 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
592 MethodBuilder mb = tb.DefineMethod (mname, MethodAttributes.Public,
593 typeof (void), new Type [] { typeof (int), typeof (string) });
594 ConstructorInfo attrCtor = typeof (SuppressUnmanagedCodeSecurityAttribute).
595 GetConstructor (new Type [0]);
596 CustomAttributeBuilder caBuilder = new CustomAttributeBuilder (
597 attrCtor, new object [0]);
598 Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#1");
599 mb.SetCustomAttribute (caBuilder);
600 //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#2");
601 mb.GetILGenerator ().Emit (OpCodes.Ret);
602 Type emittedType = tb.CreateType ();
603 MethodInfo emittedMethod = emittedType.GetMethod (mname);
604 Assert.AreEqual (MethodAttributes.HasSecurity, emittedMethod.Attributes & MethodAttributes.HasSecurity, "#3");
605 //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#4");
606 object [] emittedAttrs = emittedMethod.GetCustomAttributes (typeof (SuppressUnmanagedCodeSecurityAttribute), true);
607 Assert.AreEqual (1, emittedAttrs.Length, "#5");
610 [AttributeUsage (AttributeTargets.Parameter)]
611 class PrivateAttribute : Attribute
614 public PrivateAttribute ()
620 public void GetCustomAttributes ()
622 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
623 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public,
625 new Type [1] { typeof (int) });
626 mb.GetILGenerator ().Emit (OpCodes.Ret);
628 Type attrType = typeof (ObsoleteAttribute);
629 ConstructorInfo ctorInfo =
630 attrType.GetConstructor (new Type [] { typeof (String) });
632 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
634 // Check that attributes not accessible are not returned
635 mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (PrivateAttribute).GetConstructor (new Type [0]), new object [] { }));
637 Type t = tb.CreateType ();
639 // Try the created type
641 MethodInfo mi = t.GetMethod ("foo");
642 object [] attrs = mi.GetCustomAttributes (true);
644 Assert.AreEqual (1, attrs.Length, "#A1");
645 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#A2");
646 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#A3");
649 // Try the type builder
651 MethodInfo mi = tb.GetMethod ("foo");
652 object [] attrs = mi.GetCustomAttributes (true);
654 Assert.AreEqual (1, attrs.Length, "#B1");
655 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#B2");
656 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#B3");
661 [ExpectedException (typeof (InvalidOperationException))]
662 public void TestAddDeclarativeSecurityAlreadyCreated ()
664 MethodBuilder mb = genClass.DefineMethod (
665 genMethodName (), MethodAttributes.Public, typeof (void),
667 ILGenerator ilgen = mb.GetILGenerator ();
668 ilgen.Emit (OpCodes.Ret);
669 genClass.CreateType ();
671 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
672 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
676 [ExpectedException (typeof (ArgumentNullException))]
677 public void TestAddDeclarativeSecurityNullPermissionSet ()
679 MethodBuilder mb = genClass.DefineMethod (
680 genMethodName (), MethodAttributes.Public, typeof (void),
682 mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
686 public void TestAddDeclarativeSecurityInvalidAction ()
688 MethodBuilder mb = genClass.DefineMethod (
689 genMethodName (), MethodAttributes.Public, typeof (void),
692 SecurityAction [] actions = new SecurityAction [] {
693 SecurityAction.RequestMinimum,
694 SecurityAction.RequestOptional,
695 SecurityAction.RequestRefuse };
696 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
698 foreach (SecurityAction action in actions) {
700 mb.AddDeclarativeSecurity (action, set);
702 } catch (ArgumentOutOfRangeException) {
708 [ExpectedException (typeof (InvalidOperationException))]
709 public void TestAddDeclarativeSecurityDuplicateAction ()
711 MethodBuilder mb = genClass.DefineMethod (
712 genMethodName (), MethodAttributes.Public, typeof (void),
714 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
715 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
716 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
719 [AttributeUsage (AttributeTargets.Parameter)]
720 class ParamAttribute : Attribute
723 public ParamAttribute ()
729 public void TestDynamicParams ()
731 string mname = genMethodName ();
733 MethodBuilder mb = genClass.DefineMethod (
734 mname, MethodAttributes.Public, typeof (void),
735 new Type [] { typeof (int), typeof (string) });
736 ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
738 pb.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute).GetConstructors () [0], new object [] { }));
739 ParameterBuilder pb2 = mb.DefineParameter (2, 0, "bar");
740 pb2.SetConstant ("foo");
741 mb.GetILGenerator ().Emit (OpCodes.Ret);
743 Type t = genClass.CreateType ();
744 MethodInfo m = t.GetMethod (mname);
745 ParameterInfo [] pi = m.GetParameters ();
747 Assert.AreEqual ("foo", pi [0].Name, "#A1");
748 Assert.IsTrue (pi [0].IsIn, "#A2");
749 Assert.AreEqual (52, pi [0].DefaultValue, "#A3");
750 object [] cattrs = pi [0].GetCustomAttributes (true);
751 Assert.AreEqual (1, cattrs.Length, "#A4");
752 Assert.AreEqual (typeof (InAttribute), cattrs [0].GetType (), "#A5");
754 cattrs = pi [1].GetCustomAttributes (true);
755 Assert.AreEqual ("foo", pi [1].DefaultValue, "#B1");
759 public void SetCustomAttribute_DllImport1 ()
761 string mname = genMethodName ();
763 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
764 MethodBuilder mb = tb.DefineMethod (
765 mname, MethodAttributes.Public, typeof (void),
766 new Type [] { typeof (int), typeof (string) });
768 // Create an attribute with default values
769 mb.SetCustomAttribute (new CustomAttributeBuilder(typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "kernel32" }));
771 Type t = tb.CreateType ();
773 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
775 Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1");
776 Assert.AreEqual (mname, attr.EntryPoint, "#2");
777 Assert.AreEqual ("kernel32", attr.Value, "#3");
778 Assert.IsFalse (attr.ExactSpelling, "#4");
779 Assert.IsTrue (attr.PreserveSig, "#5");
780 Assert.IsFalse (attr.SetLastError, "#6");
781 Assert.IsFalse (attr.BestFitMapping, "#7");
782 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#8");
786 public void SetCustomAttribute_DllImport2 () {
787 string mname = genMethodName ();
789 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
790 MethodBuilder mb = tb.DefineMethod (
791 mname, MethodAttributes.Public, typeof (void),
792 new Type [] { typeof (int), typeof (string) });
794 CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] {typeof (DllImportAttribute).GetField ("EntryPoint"), typeof (DllImportAttribute).GetField ("CallingConvention"), typeof (DllImportAttribute).GetField ("CharSet"), typeof (DllImportAttribute).GetField ("ExactSpelling"), typeof (DllImportAttribute).GetField ("PreserveSig")}, new object [] { "bar", CallingConvention.StdCall, CharSet.Unicode, true, false });
795 mb.SetCustomAttribute (cb);
797 Type t = tb.CreateType ();
799 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
801 Assert.AreEqual (CallingConvention.StdCall, attr.CallingConvention, "#1");
802 Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#2");
803 Assert.AreEqual ("bar", attr.EntryPoint, "#3");
804 Assert.AreEqual ("foo", attr.Value, "#4");
805 Assert.IsTrue (attr.ExactSpelling, "#5");
806 Assert.IsFalse (attr.PreserveSig, "#6");
807 Assert.IsFalse (attr.SetLastError, "#7");
808 Assert.IsFalse (attr.BestFitMapping, "#8");
809 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#9");
813 public void SetCustomAttribute_DllImport3 () {
814 string mname = genMethodName ();
816 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
817 MethodBuilder mb = tb.DefineMethod (
818 mname, MethodAttributes.Public, typeof (void),
819 new Type [] { typeof (int), typeof (string) });
821 // Test attributes with three values (on/off/missing)
822 CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { false, false });
823 mb.SetCustomAttribute (cb);
825 Type t = tb.CreateType ();
827 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
829 Assert.IsFalse (attr.BestFitMapping, "#1");
830 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#2");
834 public void SetCustomAttribute_DllImport4 ()
836 string mname = genMethodName ();
838 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
839 MethodBuilder mb = tb.DefineMethod (
840 mname, MethodAttributes.Public, typeof (void),
841 new Type [] { typeof (int), typeof (string) });
843 CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("SetLastError"), typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { true, true, true });
844 mb.SetCustomAttribute (cb);
846 Type t = tb.CreateType ();
848 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
850 Assert.IsTrue (attr.SetLastError, "#1");
851 Assert.IsTrue (attr.BestFitMapping, "#2");
852 Assert.IsTrue (attr.ThrowOnUnmappableChar, "#3");
855 public class GenericFoo <T> {
856 public static T field;
860 public void ILGen_GenericTypeParameterBuilder ()
862 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
863 MethodBuilder mb = tb.DefineMethod ("box_int",
864 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { typeof (int) });
866 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
868 ILGenerator ilgen = mb.GetILGenerator ();
869 ilgen.Emit (OpCodes.Ldarg_0);
870 ilgen.Emit (OpCodes.Box, pars [0]);
871 ilgen.Emit (OpCodes.Ret);
873 Type t = tb.CreateType ();
874 MethodInfo mi = t.GetMethod ("box_int");
875 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
876 Assert.AreEqual (1, mi2.Invoke (null, new object [] { 1 }));
879 public void ILGen_InstantiatedGenericType ()
881 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
882 MethodBuilder mb = tb.DefineMethod ("return_type",
883 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
885 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
887 ILGenerator ilgen = mb.GetILGenerator ();
889 Type genericFoo = typeof (GenericFoo<int>).GetGenericTypeDefinition ().MakeGenericType (new Type [] { pars [0] });
891 ilgen.Emit (OpCodes.Ldtoken, genericFoo);
892 ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
893 ilgen.Emit (OpCodes.Ret);
895 Type t = tb.CreateType ();
896 MethodInfo mi = t.GetMethod ("box_int");
897 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
898 Assert.AreEqual (typeof (GenericFoo<int>), mi2.Invoke (null, new object [] { 1 }));
901 public void ILGen_InstantiatedTypeBuilder ()
903 TypeBuilder genericTb = module.DefineType (genTypeName (), TypeAttributes.Public);
904 genericTb.DefineGenericParameters (new string [] { "foo" });
905 Type generatedGenericType = genericTb.CreateType ();
907 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
908 MethodBuilder mb = tb.DefineMethod ("return_type",
909 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
911 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
913 ILGenerator ilgen = mb.GetILGenerator ();
915 ilgen.Emit (OpCodes.Ldtoken, genericTb.MakeGenericType (new Type [] { pars [0] }));
916 ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
917 ilgen.Emit (OpCodes.Ret);
919 Type t = tb.CreateType ();
920 MethodInfo mi = t.GetMethod ("return_type");
921 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
922 Assert.AreEqual (generatedGenericType.MakeGenericType (new Type [] { typeof (int) }), mi2.Invoke (null, new object [] { 1 }));
926 public void Bug354757 ()
928 TypeBuilder gtb = module.DefineType (genTypeName (), TypeAttributes.Public);
929 gtb.DefineGenericParameters ("T");
930 MethodBuilder mb = gtb.DefineMethod ("foo", MethodAttributes.Public);
931 mb.DefineGenericParameters ("S");
932 Assert.IsTrue (mb.IsGenericMethodDefinition);
934 Type gt = gtb.MakeGenericType (typeof (object));
935 MethodInfo m = TypeBuilder.GetMethod (gt, mb);
936 Assert.IsTrue (m.IsGenericMethodDefinition);
938 MethodInfo mopen = m.MakeGenericMethod (m.GetGenericArguments ());
939 Assert.IsFalse (mopen.IsGenericMethodDefinition);
943 public void DefineGenericParameters_Names_Empty ()
945 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
946 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
949 mb.DefineGenericParameters (new string [0]);
951 } catch (ArgumentException ex) {
952 // Value does not fall within the expected range
953 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
954 Assert.IsNull (ex.InnerException, "#3");
955 Assert.IsNotNull (ex.Message, "#4");
956 Assert.IsNull (ex.ParamName, "#5");
963 public void DefineGenericParameters_Names_Null ()
965 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
966 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
969 mb.DefineGenericParameters ((string []) null);
971 } catch (ArgumentNullException ex) {
972 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
973 Assert.IsNull (ex.InnerException, "#A3");
974 Assert.IsNotNull (ex.Message, "#A4");
975 Assert.AreEqual ("names", ex.ParamName, "#A5");
979 mb.DefineGenericParameters ("K", null, "V");
981 } catch (ArgumentNullException ex) {
982 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
983 Assert.IsNull (ex.InnerException, "#B3");
984 Assert.IsNotNull (ex.Message, "#B4");
985 Assert.AreEqual ("names", ex.ParamName, "#B5");
990 public static int Foo<T> (T a, T b) {
995 public void GenericMethodIsProperlyInflated ()
997 var tb = module.DefineType ("foo");
998 var met = typeof (MethodBuilderTest).GetMethod ("Foo");
1000 var mb = tb.DefineMethod ("myFunc", MethodAttributes.Public | MethodAttributes.Static, typeof (int), Type.EmptyTypes);
1001 var garg = mb.DefineGenericParameters ("a") [0];
1002 mb.SetParameters (garg, garg);
1004 var ilgen = mb.GetILGenerator ();
1005 ilgen.Emit (OpCodes.Ldarg_0);
1006 ilgen.Emit (OpCodes.Ldarg_1);
1007 ilgen.Emit (OpCodes.Call, met.MakeGenericMethod (garg));
1008 ilgen.Emit (OpCodes.Ret);
1010 var res = tb.CreateType ();
1011 var mm = res.GetMethod ("myFunc").MakeGenericMethod (typeof (int));
1013 var rt = mm.Invoke (null, new object[] { 10, 20 });
1014 Assert.AreEqual (99, rt, "#1");
1017 public static void VarargMethod (string headline, __arglist) {
1018 ArgIterator ai = new ArgIterator (__arglist);
1020 Console.Write (headline);
1021 while (ai.GetRemainingCount () > 0)
1022 Console.Write (TypedReference.ToObject (ai.GetNextArg ()));
1023 Console.WriteLine ();
1027 public void CanCallVarargMethods ()
1029 var tb = module.DefineType ("foo");
1030 MethodBuilder mb = tb.DefineMethod ("CallVarargMethod",
1031 MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
1032 typeof (void), Type.EmptyTypes);
1034 ILGenerator il = mb.GetILGenerator ();
1035 MethodInfo miVarargMethod = typeof (MethodBuilderTest).GetMethod ("VarargMethod");
1037 il.Emit (OpCodes.Ldstr, "Hello world from ");
1038 il.Emit (OpCodes.Call, typeof(Assembly).GetMethod ("GetExecutingAssembly"));
1039 il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof(Assembly) });
1041 il.Emit (OpCodes.Ldstr, "Current time: ");
1042 il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_Now"));
1043 il.Emit (OpCodes.Ldstr, " (UTC ");
1044 il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_UtcNow"));
1045 il.Emit (OpCodes.Ldstr, ")");
1046 il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof (DateTime), typeof (string), typeof (DateTime), typeof (string) });
1047 il.Emit (OpCodes.Ret);
1049 Type type = tb.CreateType ();
1050 type.GetMethod ("CallVarargMethod").Invoke (null, null);
1053 public static string GenericMethodWithOneArg<T> (T t)
1055 return t.ToString ();
1059 public void ParamerersOfGenericArgumentsAreProperlyEncoded ()
1061 var type = module.DefineType (
1063 TypeAttributes.Public
1064 | TypeAttributes.Abstract
1065 | TypeAttributes.Sealed,
1068 var foo_method = typeof (MethodBuilderTest).GetMethod ("GenericMethodWithOneArg");
1070 var method = type.DefineMethod (
1072 MethodAttributes.Static | MethodAttributes.Public,
1074 new [] { foo_method.GetGenericArguments () [0] });
1075 method.DefineGenericParameters ("K");
1077 var il = method.GetILGenerator ();
1078 il.Emit (OpCodes.Ldarga, 0);
1079 il.Emit (OpCodes.Constrained, method.GetGenericArguments () [0]);
1080 il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString"));
1081 il.Emit (OpCodes.Ret);
1085 var re_foo_open = module.GetType ("Bar").GetMethod ("ReFoo");
1087 Assert.AreEqual (re_foo_open.GetGenericArguments ()[0], re_foo_open.GetParameters () [0].ParameterType, "#1");
1091 public void CanCallGetMethodBodyOnDynamicImageMethod ()
1093 var type = module.DefineType (
1094 "CanCallGetMethodBodyOnDynamicImageMethod",
1095 TypeAttributes.Public,
1098 var baz = type.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Static, typeof (object), Type.EmptyTypes);
1100 var il = baz.GetILGenerator ();
1101 var temp = il.DeclareLocal (typeof (object));
1102 il.Emit (OpCodes.Ldnull);
1103 il.Emit (OpCodes.Stloc, temp);
1104 il.Emit (OpCodes.Ldloc, temp);
1105 il.Emit (OpCodes.Ret);
1107 var body = type.CreateType ().GetMethod ("Foo").GetMethodBody ();
1109 Assert.IsNotNull (body);
1110 Assert.AreEqual (1, body.LocalVariables.Count);
1111 Assert.AreEqual (typeof (object), body.LocalVariables [0].LocalType);
1116 public void GetGenericArgumentsReturnsNullForNonGenericMethod ()
1118 var tb = module.DefineType ("Base");
1120 var mb = tb.DefineMethod ("foo", MethodAttributes.Public, typeof (void), Type.EmptyTypes);
1122 Assert.IsNull (mb.GetGenericArguments ());
1127 [ExpectedException (typeof (ArgumentException))]
1128 public void SetConstantIllegalType ()
1130 var tb = module.DefineType ("Base");
1132 var mb = tb.DefineMethod ("foo", MethodAttributes.Public, typeof (void), new Type [] { typeof (decimal) });
1133 ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
1134 pb.SetConstant (5m);
1137 public interface ITest
1139 T[] Method<T>(T[] value);
1144 public void ArrayOfGenericParam ()
1146 var tb = module.DefineType ("Base");
1148 tb.AddInterfaceImplementation (typeof (ITest));
1150 var testMethod = tb.DefineMethod ("Method", MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis);
1152 var testParameters = Array.ConvertAll (testMethod.DefineGenericParameters("T"), b => (Type)b);
1154 var returnType = testParameters[0].MakeArrayType();
1156 testMethod.SetParameters (testParameters[0].MakeArrayType());
1157 testMethod.SetReturnType (returnType);
1159 var testIl = testMethod.GetILGenerator ();
1160 testIl.Emit (OpCodes.Ldarg_1);
1161 testIl.Emit (OpCodes.Castclass, returnType);
1162 testIl.Emit (OpCodes.Ret);
1164 var t = tb.CreateType ();
1166 var test = (ITest) Activator.CreateInstance (t);
1169 var returnValue = test.Method (o);
1171 Assert.AreEqual (o, returnValue);