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) {
288 // MS.NET 2.x no longer allows a zero length method body
290 [ExpectedException (typeof (InvalidOperationException))]
292 public void ZeroLengthBodyTest1 ()
294 MethodBuilder mb = genClass.DefineMethod (
295 genMethodName (), 0, typeof (void),
296 new Type [2] { typeof (int), typeof (int) });
297 mb.CreateMethodBody (new byte [2], 0);
298 genClass.CreateType ();
301 // A zero length method body can be created
303 public void ZeroLengthBodyTest2 ()
305 MethodBuilder mb = genClass.DefineMethod (
306 genMethodName (), 0, typeof (void),
307 new Type [2] { typeof (int), typeof (int) });
308 mb.CreateMethodBody (new byte [2], 0);
312 public void TestHashCode ()
314 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
315 string methodName = genMethodName ();
316 MethodBuilder mb = tb.DefineMethod (methodName, 0, typeof (void),
317 new Type [2] { typeof(int), typeof(int) });
318 Assert.AreEqual (methodName.GetHashCode (), mb.GetHashCode ());
322 public void TestGetBaseDefinition ()
324 MethodBuilder mb = genClass.DefineMethod (
325 genMethodName (), 0, typeof (void), new Type [0]);
326 Assert.AreEqual (mb.GetBaseDefinition (), mb);
330 public void TestGetILGenerator ()
332 MethodBuilder mb = genClass.DefineMethod (
333 genMethodName (), 0, typeof (void), new Type [0]);
335 // The same instance is returned on the second call
336 ILGenerator ilgen1 = mb.GetILGenerator ();
337 ILGenerator ilgen2 = mb.GetILGenerator ();
339 Assert.AreEqual (ilgen1, ilgen2, "#1");
341 // Does not work on unmanaged code
342 MethodBuilder mb2 = genClass.DefineMethod (
343 genMethodName (), 0, typeof (void), new Type [0]);
345 mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);
346 mb2.GetILGenerator ();
348 } catch (InvalidOperationException) {
351 mb2.SetImplementationFlags (MethodImplAttributes.Native);
352 mb2.GetILGenerator ();
354 } catch (InvalidOperationException) {
359 public void TestMethodImplementationFlags ()
361 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
362 MethodBuilder mb = tb.DefineMethod (
363 genMethodName (), 0, typeof (void), new Type [0]);
365 Assert.AreEqual (MethodImplAttributes.Managed | MethodImplAttributes.IL,
366 mb.GetMethodImplementationFlags (), "#1");
368 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
370 Assert.AreEqual (MethodImplAttributes.OPTIL, mb.GetMethodImplementationFlags (), "#2");
372 mb.CreateMethodBody (new byte [2], 1);
373 mb.SetImplementationFlags (MethodImplAttributes.Managed);
376 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
378 } catch (InvalidOperationException) {
383 public void TestGetModule ()
385 MethodBuilder mb = genClass.DefineMethod (
386 genMethodName (), 0, typeof (void), new Type [0]);
387 Assert.AreEqual (module, mb.GetModule ());
391 public void TestGetParameters ()
393 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
394 MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
395 new Type [1] { typeof (void) });
398 * According to the MSDN docs, this method should fail with a
399 * NotSupportedException. In reality, it throws an
400 * InvalidOperationException under MS .NET, and returns the
401 * requested data under mono.
407 } catch (InvalidOperationException ex) {
408 Console.WriteLine (ex);
414 public void TestGetToken ()
416 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
417 MethodBuilder mb = tb.DefineMethod (
418 genMethodName (), 0, typeof (void), new Type [1] { typeof (void) });
423 public void TestInvoke ()
425 MethodBuilder mb = genClass.DefineMethod (
426 genMethodName (), 0, typeof (void),
427 new Type [1] { typeof (int) });
430 mb.Invoke (null, new object [1] { 42 });
432 } catch (NotSupportedException) {
436 mb.Invoke (null, 0, null, new object [1] { 42 }, null);
438 } catch (NotSupportedException) {
443 [ExpectedException (typeof (NotSupportedException))]
444 public void TestIsDefined ()
446 MethodBuilder mb = genClass.DefineMethod (
447 genMethodName (), 0, typeof (void),
448 new Type [1] { typeof (int) });
449 mb.IsDefined (null, true);
453 public void TestGetCustomAttributes_Incomplete ()
455 MethodBuilder mb = genClass.DefineMethod (
456 genMethodName (), 0, typeof (void),
457 new Type [1] { typeof (int) });
460 mb.GetCustomAttributes (true);
462 } catch (NotSupportedException) {
466 mb.GetCustomAttributes (null, true);
468 } catch (NotSupportedException) {
473 [Category ("NotWorking")]
474 public void TestGetCustomAttributes_Complete ()
476 MethodBuilder mb = genClass.DefineMethod (
477 genMethodName (), 0, typeof (void),
478 new Type [1] { typeof (int) });
479 mb.GetILGenerator ().Emit (OpCodes.Ret);
480 genClass.CreateType ();
483 mb.GetCustomAttributes (true);
485 } catch (NotSupportedException) {
489 mb.GetCustomAttributes (null, true);
491 } catch (NotSupportedException) {
496 public void TestSetCustomAttribute ()
498 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
499 string name = genMethodName ();
500 MethodBuilder mb = tb.DefineMethod (
501 name, MethodAttributes.Public, typeof (void),
502 new Type [1] { typeof (int) });
506 mb.SetCustomAttribute (null);
508 } catch (ArgumentNullException) {
511 byte [] custAttrData = { 1, 0, 0, 0, 0 };
512 Type attrType = Type.GetType
513 ("System.Reflection.AssemblyKeyNameAttribute");
514 Type [] paramTypes = new Type [1];
515 paramTypes [0] = typeof (String);
516 ConstructorInfo ctorInfo =
517 attrType.GetConstructor (paramTypes);
519 mb.SetCustomAttribute (ctorInfo, custAttrData);
521 // Test MethodImplAttribute
522 mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute).GetConstructor (new Type [1] { typeof (short) }), new object [1] { (short) MethodImplAttributes.Synchronized }));
523 mb.GetILGenerator ().Emit (OpCodes.Ret);
525 Type t = tb.CreateType ();
527 Assert.AreEqual (t.GetMethod (name).GetMethodImplementationFlags (),
528 MethodImplAttributes.Synchronized, "#2");
530 // Null arguments again
532 mb.SetCustomAttribute (null, new byte [2]);
534 } catch (ArgumentNullException) {
538 mb.SetCustomAttribute (ctorInfo, null);
540 } catch (ArgumentNullException) {
545 public void SetCustomAttribute_DllImport_DllName_Empty ()
547 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
548 MethodBuilder mb = tb.DefineMethod (genMethodName (),
549 MethodAttributes.Public, typeof (void),
550 new Type [1] { typeof (int) });
552 ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
553 new Type [] { typeof (string) });
555 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
556 new object [] { string.Empty }));
558 } catch (ArgumentException ex) {
559 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
560 Assert.IsNull (ex.InnerException, "#3");
561 Assert.IsNotNull (ex.Message, "#4");
562 Assert.IsNull (ex.ParamName, "#5");
567 public void SetCustomAttribute_DllImport_DllName_Null ()
569 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
570 MethodBuilder mb = tb.DefineMethod (genMethodName (),
571 MethodAttributes.Public, typeof (void),
572 new Type [1] { typeof (int) });
574 ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
575 new Type [] { typeof (string) });
577 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
578 new object [] { null }));
580 } catch (ArgumentException ex) {
581 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
582 Assert.IsNull (ex.InnerException, "#3");
583 Assert.IsNotNull (ex.Message, "#4");
584 Assert.IsNull (ex.ParamName, "#5");
589 public void SetCustomAttribute_SuppressUnmanagedCodeSecurity ()
591 string mname = genMethodName ();
593 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
594 MethodBuilder mb = tb.DefineMethod (mname, MethodAttributes.Public,
595 typeof (void), new Type [] { typeof (int), typeof (string) });
596 ConstructorInfo attrCtor = typeof (SuppressUnmanagedCodeSecurityAttribute).
597 GetConstructor (new Type [0]);
598 CustomAttributeBuilder caBuilder = new CustomAttributeBuilder (
599 attrCtor, new object [0]);
600 Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#1");
601 mb.SetCustomAttribute (caBuilder);
602 //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#2");
603 mb.GetILGenerator ().Emit (OpCodes.Ret);
604 Type emittedType = tb.CreateType ();
605 MethodInfo emittedMethod = emittedType.GetMethod (mname);
606 Assert.AreEqual (MethodAttributes.HasSecurity, emittedMethod.Attributes & MethodAttributes.HasSecurity, "#3");
607 //Assert.IsTrue ((mb.Attributes & MethodAttributes.HasSecurity) == 0, "#4");
608 object [] emittedAttrs = emittedMethod.GetCustomAttributes (typeof (SuppressUnmanagedCodeSecurityAttribute), true);
609 Assert.AreEqual (1, emittedAttrs.Length, "#5");
612 [AttributeUsage (AttributeTargets.Parameter)]
613 class PrivateAttribute : Attribute
616 public PrivateAttribute ()
622 public void GetCustomAttributes ()
624 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
625 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public,
627 new Type [1] { typeof (int) });
628 mb.GetILGenerator ().Emit (OpCodes.Ret);
630 Type attrType = typeof (ObsoleteAttribute);
631 ConstructorInfo ctorInfo =
632 attrType.GetConstructor (new Type [] { typeof (String) });
634 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
636 // Check that attributes not accessible are not returned
637 mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (PrivateAttribute).GetConstructor (new Type [0]), new object [] { }));
639 Type t = tb.CreateType ();
641 // Try the created type
643 MethodInfo mi = t.GetMethod ("foo");
644 object [] attrs = mi.GetCustomAttributes (true);
646 Assert.AreEqual (1, attrs.Length, "#A1");
647 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#A2");
648 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#A3");
651 // Try the type builder
653 MethodInfo mi = tb.GetMethod ("foo");
654 object [] attrs = mi.GetCustomAttributes (true);
656 Assert.AreEqual (1, attrs.Length, "#B1");
657 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#B2");
658 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#B3");
663 [ExpectedException (typeof (InvalidOperationException))]
664 public void TestAddDeclarativeSecurityAlreadyCreated ()
666 MethodBuilder mb = genClass.DefineMethod (
667 genMethodName (), MethodAttributes.Public, typeof (void),
669 ILGenerator ilgen = mb.GetILGenerator ();
670 ilgen.Emit (OpCodes.Ret);
671 genClass.CreateType ();
673 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
674 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
678 [ExpectedException (typeof (ArgumentNullException))]
679 public void TestAddDeclarativeSecurityNullPermissionSet ()
681 MethodBuilder mb = genClass.DefineMethod (
682 genMethodName (), MethodAttributes.Public, typeof (void),
684 mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
688 public void TestAddDeclarativeSecurityInvalidAction ()
690 MethodBuilder mb = genClass.DefineMethod (
691 genMethodName (), MethodAttributes.Public, typeof (void),
694 SecurityAction [] actions = new SecurityAction [] {
695 SecurityAction.RequestMinimum,
696 SecurityAction.RequestOptional,
697 SecurityAction.RequestRefuse };
698 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
700 foreach (SecurityAction action in actions) {
702 mb.AddDeclarativeSecurity (action, set);
704 } catch (ArgumentOutOfRangeException) {
710 [ExpectedException (typeof (InvalidOperationException))]
711 public void TestAddDeclarativeSecurityDuplicateAction ()
713 MethodBuilder mb = genClass.DefineMethod (
714 genMethodName (), MethodAttributes.Public, typeof (void),
716 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
717 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
718 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
721 [AttributeUsage (AttributeTargets.Parameter)]
722 class ParamAttribute : Attribute
725 public ParamAttribute ()
731 public void TestDynamicParams ()
733 string mname = genMethodName ();
735 MethodBuilder mb = genClass.DefineMethod (
736 mname, MethodAttributes.Public, typeof (void),
737 new Type [] { typeof (int), typeof (string) });
738 ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
740 pb.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute).GetConstructors () [0], new object [] { }));
741 ParameterBuilder pb2 = mb.DefineParameter (2, 0, "bar");
742 pb2.SetConstant ("foo");
743 mb.GetILGenerator ().Emit (OpCodes.Ret);
745 Type t = genClass.CreateType ();
746 MethodInfo m = t.GetMethod (mname);
747 ParameterInfo [] pi = m.GetParameters ();
749 Assert.AreEqual ("foo", pi [0].Name, "#A1");
750 Assert.IsTrue (pi [0].IsIn, "#A2");
751 Assert.AreEqual (52, pi [0].DefaultValue, "#A3");
752 object [] cattrs = pi [0].GetCustomAttributes (true);
754 Assert.AreEqual (1, cattrs.Length, "#A4");
755 Assert.AreEqual (typeof (InAttribute), cattrs [0].GetType (), "#A5");
757 Assert.AreEqual (0, cattrs.Length, "#A4");
760 cattrs = pi [1].GetCustomAttributes (true);
761 Assert.AreEqual ("foo", pi [1].DefaultValue, "#B1");
765 public void SetCustomAttribute_DllImport1 ()
767 string mname = genMethodName ();
769 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
770 MethodBuilder mb = tb.DefineMethod (
771 mname, MethodAttributes.Public, typeof (void),
772 new Type [] { typeof (int), typeof (string) });
774 // Create an attribute with default values
775 mb.SetCustomAttribute (new CustomAttributeBuilder(typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "kernel32" }));
777 Type t = tb.CreateType ();
779 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
781 Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1");
782 Assert.AreEqual (mname, attr.EntryPoint, "#2");
783 Assert.AreEqual ("kernel32", attr.Value, "#3");
784 Assert.IsFalse (attr.ExactSpelling, "#4");
785 Assert.IsTrue (attr.PreserveSig, "#5");
786 Assert.IsFalse (attr.SetLastError, "#6");
787 Assert.IsFalse (attr.BestFitMapping, "#7");
788 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#8");
792 public void SetCustomAttribute_DllImport2 () {
793 string mname = genMethodName ();
795 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
796 MethodBuilder mb = tb.DefineMethod (
797 mname, MethodAttributes.Public, typeof (void),
798 new Type [] { typeof (int), typeof (string) });
800 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 });
801 mb.SetCustomAttribute (cb);
803 Type t = tb.CreateType ();
805 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
807 Assert.AreEqual (CallingConvention.StdCall, attr.CallingConvention, "#1");
808 Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#2");
809 Assert.AreEqual ("bar", attr.EntryPoint, "#3");
810 Assert.AreEqual ("foo", attr.Value, "#4");
811 Assert.IsTrue (attr.ExactSpelling, "#5");
812 Assert.IsFalse (attr.PreserveSig, "#6");
813 Assert.IsFalse (attr.SetLastError, "#7");
814 Assert.IsFalse (attr.BestFitMapping, "#8");
815 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#9");
819 public void SetCustomAttribute_DllImport3 () {
820 string mname = genMethodName ();
822 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
823 MethodBuilder mb = tb.DefineMethod (
824 mname, MethodAttributes.Public, typeof (void),
825 new Type [] { typeof (int), typeof (string) });
827 // Test attributes with three values (on/off/missing)
828 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 });
829 mb.SetCustomAttribute (cb);
831 Type t = tb.CreateType ();
833 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
835 Assert.IsFalse (attr.BestFitMapping, "#1");
836 Assert.IsFalse (attr.ThrowOnUnmappableChar, "#2");
840 public void SetCustomAttribute_DllImport4 ()
842 string mname = genMethodName ();
844 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
845 MethodBuilder mb = tb.DefineMethod (
846 mname, MethodAttributes.Public, typeof (void),
847 new Type [] { typeof (int), typeof (string) });
849 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 });
850 mb.SetCustomAttribute (cb);
852 Type t = tb.CreateType ();
854 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
856 Assert.IsTrue (attr.SetLastError, "#1");
857 Assert.IsTrue (attr.BestFitMapping, "#2");
858 Assert.IsTrue (attr.ThrowOnUnmappableChar, "#3");
861 public class GenericFoo <T> {
862 public static T field;
866 public void ILGen_GenericTypeParameterBuilder ()
868 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
869 MethodBuilder mb = tb.DefineMethod ("box_int",
870 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { typeof (int) });
872 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
874 ILGenerator ilgen = mb.GetILGenerator ();
875 ilgen.Emit (OpCodes.Ldarg_0);
876 ilgen.Emit (OpCodes.Box, pars [0]);
877 ilgen.Emit (OpCodes.Ret);
879 Type t = tb.CreateType ();
880 MethodInfo mi = t.GetMethod ("box_int");
881 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
882 Assert.AreEqual (1, mi2.Invoke (null, new object [] { 1 }));
885 public void ILGen_InstantiatedGenericType ()
887 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
888 MethodBuilder mb = tb.DefineMethod ("return_type",
889 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
891 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
893 ILGenerator ilgen = mb.GetILGenerator ();
895 Type genericFoo = typeof (GenericFoo<int>).GetGenericTypeDefinition ().MakeGenericType (new Type [] { pars [0] });
897 ilgen.Emit (OpCodes.Ldtoken, genericFoo);
898 ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
899 ilgen.Emit (OpCodes.Ret);
901 Type t = tb.CreateType ();
902 MethodInfo mi = t.GetMethod ("box_int");
903 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
904 Assert.AreEqual (typeof (GenericFoo<int>), mi2.Invoke (null, new object [] { 1 }));
907 public void ILGen_InstantiatedTypeBuilder ()
909 TypeBuilder genericTb = module.DefineType (genTypeName (), TypeAttributes.Public);
910 genericTb.DefineGenericParameters (new string [] { "foo" });
911 Type generatedGenericType = genericTb.CreateType ();
913 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
914 MethodBuilder mb = tb.DefineMethod ("return_type",
915 MethodAttributes.Public|MethodAttributes.Static, typeof (object), new Type [] { });
917 GenericTypeParameterBuilder[] pars = mb.DefineGenericParameters (new string [] { "foo" });
919 ILGenerator ilgen = mb.GetILGenerator ();
921 ilgen.Emit (OpCodes.Ldtoken, genericTb.MakeGenericType (new Type [] { pars [0] }));
922 ilgen.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle"));
923 ilgen.Emit (OpCodes.Ret);
925 Type t = tb.CreateType ();
926 MethodInfo mi = t.GetMethod ("return_type");
927 MethodInfo mi2 = mi.MakeGenericMethod (new Type [] { typeof (int) });
928 Assert.AreEqual (generatedGenericType.MakeGenericType (new Type [] { typeof (int) }), mi2.Invoke (null, new object [] { 1 }));
932 public void Bug354757 ()
934 TypeBuilder gtb = module.DefineType (genTypeName (), TypeAttributes.Public);
935 gtb.DefineGenericParameters ("T");
936 MethodBuilder mb = gtb.DefineMethod ("foo", MethodAttributes.Public);
937 mb.DefineGenericParameters ("S");
938 Assert.IsTrue (mb.IsGenericMethodDefinition);
940 Type gt = gtb.MakeGenericType (typeof (object));
941 MethodInfo m = TypeBuilder.GetMethod (gt, mb);
942 Assert.IsTrue (m.IsGenericMethodDefinition);
944 MethodInfo mopen = m.MakeGenericMethod (m.GetGenericArguments ());
945 Assert.IsFalse (mopen.IsGenericMethodDefinition);
949 public void DefineGenericParameters_Names_Empty ()
951 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
952 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
955 mb.DefineGenericParameters (new string [0]);
957 } catch (ArgumentException ex) {
958 // Value does not fall within the expected range
959 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
960 Assert.IsNull (ex.InnerException, "#3");
961 Assert.IsNotNull (ex.Message, "#4");
962 Assert.IsNull (ex.ParamName, "#5");
969 public void DefineGenericParameters_Names_Null ()
971 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
972 MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public);
975 mb.DefineGenericParameters ((string []) null);
977 } catch (ArgumentNullException ex) {
978 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
979 Assert.IsNull (ex.InnerException, "#A3");
980 Assert.IsNotNull (ex.Message, "#A4");
981 Assert.AreEqual ("names", ex.ParamName, "#A5");
985 mb.DefineGenericParameters ("K", null, "V");
987 } catch (ArgumentNullException ex) {
988 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
989 Assert.IsNull (ex.InnerException, "#B3");
990 Assert.IsNotNull (ex.Message, "#B4");
991 Assert.AreEqual ("names", ex.ParamName, "#B5");
996 public static int Foo<T> (T a, T b) {
1001 public void GenericMethodIsProperlyInflated ()
1003 var tb = module.DefineType ("foo");
1004 var met = typeof (MethodBuilderTest).GetMethod ("Foo");
1006 var mb = tb.DefineMethod ("myFunc", MethodAttributes.Public | MethodAttributes.Static, typeof (int), Type.EmptyTypes);
1007 var garg = mb.DefineGenericParameters ("a") [0];
1008 mb.SetParameters (garg, garg);
1010 var ilgen = mb.GetILGenerator ();
1011 ilgen.Emit (OpCodes.Ldarg_0);
1012 ilgen.Emit (OpCodes.Ldarg_1);
1013 ilgen.Emit (OpCodes.Call, met.MakeGenericMethod (garg));
1014 ilgen.Emit (OpCodes.Ret);
1016 var res = tb.CreateType ();
1017 var mm = res.GetMethod ("myFunc").MakeGenericMethod (typeof (int));
1019 var rt = mm.Invoke (null, new object[] { 10, 20 });
1020 Assert.AreEqual (99, rt, "#1");
1023 public static void VarargMethod (string headline, __arglist) {
1024 ArgIterator ai = new ArgIterator (__arglist);
1026 Console.Write (headline);
1027 while (ai.GetRemainingCount () > 0)
1028 Console.Write (TypedReference.ToObject (ai.GetNextArg ()));
1029 Console.WriteLine ();
1033 public void CanCallVarargMethods ()
1035 var tb = module.DefineType ("foo");
1036 MethodBuilder mb = tb.DefineMethod ("CallVarargMethod",
1037 MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
1038 typeof (void), Type.EmptyTypes);
1040 ILGenerator il = mb.GetILGenerator ();
1041 MethodInfo miVarargMethod = typeof (MethodBuilderTest).GetMethod ("VarargMethod");
1043 il.Emit (OpCodes.Ldstr, "Hello world from ");
1044 il.Emit (OpCodes.Call, typeof(Assembly).GetMethod ("GetExecutingAssembly"));
1045 il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof(Assembly) });
1047 il.Emit (OpCodes.Ldstr, "Current time: ");
1048 il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_Now"));
1049 il.Emit (OpCodes.Ldstr, " (UTC ");
1050 il.Emit (OpCodes.Call, typeof(DateTime).GetMethod("get_UtcNow"));
1051 il.Emit (OpCodes.Ldstr, ")");
1052 il.EmitCall (OpCodes.Call, miVarargMethod, new Type[] { typeof (DateTime), typeof (string), typeof (DateTime), typeof (string) });
1053 il.Emit (OpCodes.Ret);
1055 Type type = tb.CreateType ();
1056 type.GetMethod ("CallVarargMethod").Invoke (null, null);