2 // System.Reflection.MethodInfo Test Cases
5 // Zoltan Varga (vargaz@gmail.com)
6 // Aleksey Kliger (aleksey@xamarin.com)
8 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2015 Xamarin, Inc. (http://www.xamarin.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using NUnit
.Framework
;
35 using System
.Threading
;
36 using System
.Reflection
;
37 #if !MONOTOUCH && !FULL_AOT_RUNTIME
38 using System
.Reflection
.Emit
;
40 using System
.Runtime
.InteropServices
;
41 using System
.Runtime
.CompilerServices
;
43 using System
.Collections
.Generic
;
46 // Disable expected warning
47 #pragma warning disable 169
48 public struct MethodInfoTestStruct
{
51 #pragma warning restore 169
53 namespace MonoTests
.System
.Reflection
56 public class MethodInfoTest
58 #if MONOTOUCH || FULL_AOT_RUNTIME
59 // use an existing symbol - so we can build without dlsym. It does not matter that the signature does not match for the test
60 [DllImport ("libc", EntryPoint
="readlink", CharSet
=CharSet
.Unicode
, ExactSpelling
=false, PreserveSig
=true, SetLastError
=true, BestFitMapping
=true, ThrowOnUnmappableChar
=true)]
62 [DllImport ("libfoo", EntryPoint
="foo", CharSet
=CharSet
.Unicode
, ExactSpelling
=false, PreserveSig
=true, SetLastError
=true, BestFitMapping
=true, ThrowOnUnmappableChar
=true)]
64 public static extern void dllImportMethod ();
65 [MethodImplAttribute(MethodImplOptions
.PreserveSig
)]
66 public void preserveSigMethod ()
70 [MethodImplAttribute(MethodImplOptions
.Synchronized
)]
71 public void synchronizedMethod ()
75 public interface InterfaceTest
81 public void IsDefined_AttributeType_Null ()
83 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("foo");
86 mi
.IsDefined ((Type
) null, false);
88 } catch (ArgumentNullException ex
) {
89 Assert
.AreEqual (typeof (ArgumentNullException
), ex
.GetType (), "#2");
90 Assert
.IsNull (ex
.InnerException
, "#3");
91 Assert
.IsNotNull (ex
.Message
, "#4");
92 Assert
.IsNotNull (ex
.ParamName
, "#5");
93 Assert
.AreEqual ("attributeType", ex
.ParamName
, "#6");
98 public void TestInvokeByRefReturnMethod ()
101 MethodInfo m
= typeof (int[]).GetMethod ("Address");
102 m
.Invoke (new int[1], new object[] { 0 }
);
104 } catch (NotSupportedException e
) {
105 Assert
.AreEqual (typeof (NotSupportedException
), e
.GetType (), "#2");
106 Assert
.IsNull (e
.InnerException
, "#3");
107 Assert
.IsNotNull (e
.Message
, "#4");
112 public void PseudoCustomAttributes ()
114 Type t
= typeof (MethodInfoTest
);
116 DllImportAttribute attr
= (DllImportAttribute
)((t
.GetMethod ("dllImportMethod").GetCustomAttributes (typeof (DllImportAttribute
), true)) [0]);
118 Assert
.AreEqual (CallingConvention
.Winapi
, attr
.CallingConvention
, "#1");
119 #if MONOTOUCH || FULL_AOT_RUNTIME
120 Assert
.AreEqual ("readlink", attr
.EntryPoint
, "#2");
121 Assert
.AreEqual ("libc", attr
.Value
, "#3");
123 Assert
.AreEqual ("foo", attr
.EntryPoint
, "#2");
124 Assert
.AreEqual ("libfoo", attr
.Value
, "#3");
126 Assert
.AreEqual (CharSet
.Unicode
, attr
.CharSet
, "#4");
127 Assert
.AreEqual (false, attr
.ExactSpelling
, "#5");
128 Assert
.AreEqual (true, attr
.PreserveSig
, "#6");
129 Assert
.AreEqual (true, attr
.SetLastError
, "#7");
130 Assert
.AreEqual (true, attr
.BestFitMapping
, "#8");
131 Assert
.AreEqual (true, attr
.ThrowOnUnmappableChar
, "#9");
133 PreserveSigAttribute attr2
= (PreserveSigAttribute
)((t
.GetMethod ("preserveSigMethod").GetCustomAttributes (true)) [0]);
135 // This doesn't work under MS.NET
137 MethodImplAttribute attr3 = (MethodImplAttribute)((t.GetMethod ("synchronizedMethod").GetCustomAttributes (true)) [0]);
141 [return: MarshalAs (UnmanagedType
.Interface
)]
142 public void ReturnTypeMarshalAs ()
147 public void ReturnTypePseudoCustomAttributes ()
149 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("ReturnTypeMarshalAs");
151 Assert
.IsTrue (mi
.ReturnTypeCustomAttributes
.GetCustomAttributes (typeof (MarshalAsAttribute
), true).Length
== 1);
154 public static int foo (int i
, int j
)
160 public void StaticInvokeWithObject ()
162 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("foo");
164 mi
.Invoke (new Object (), new object [] { 1, 2 }
);
168 public void ByRefInvoke ()
170 MethodInfo met
= typeof(MethodInfoTest
).GetMethod ("ByRefTest");
171 object[] parms
= new object[] {1}
;
172 met
.Invoke (null, parms
);
173 Assert
.AreEqual (2, parms
[0]);
176 public static void ByRefTest (ref int a1
)
182 static int byref_arg
;
184 public static void ByrefVtype (ref int i
) {
190 public void ByrefVtypeInvoke ()
192 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("ByrefVtype");
195 object[] args
= new object [] { o }
;
196 mi
.Invoke (null, args
);
197 Assert
.AreEqual (1, byref_arg
, "#A1");
198 Assert
.AreEqual (1, o
, "#A2");
199 Assert
.AreEqual (5, args
[0], "#A3");
202 mi
.Invoke (null, args
);
203 Assert
.AreEqual (0, byref_arg
, "#B1");
204 Assert
.AreEqual (5, args
[0], "#B2");
207 public void HeyHey (out string out1
, ref DateTime ref1
)
212 public void SignatureTest (__arglist
)
216 public static unsafe int* PtrFunc (int* a
)
221 #if MONO_FEATURE_THREAD_ABORT
223 public void InvokeThreadAbort ()
225 MethodInfo method
= typeof (MethodInfoTest
).GetMethod ("AbortIt");
227 method
.Invoke (null, new object [0]);
230 catch (ThreadAbortException ex
) {
231 Thread
.ResetAbort ();
232 Assert
.IsNull (ex
.InnerException
, "#2");
236 public static void AbortIt ()
238 Thread
.CurrentThread
.Abort ();
243 public void ToStringByRef ()
245 Assert
.AreEqual ("Void HeyHey(System.String ByRef, System.DateTime ByRef)",
246 this.GetType ().GetMethod ("HeyHey").ToString ());
250 public void ToStringArgList ()
252 Assert
.AreEqual ("Void SignatureTest(...)",
253 this.GetType ().GetMethod ("SignatureTest").ToString ());
257 public void ToStringWithPointerSignatures () //bug #409583
259 Assert
.AreEqual ("Int32* PtrFunc(Int32*)", this.GetType ().GetMethod ("PtrFunc").ToString ());
262 public struct SimpleStruct
267 public static unsafe SimpleStruct
* PtrFunc2 (SimpleStruct
* a
, A
.B
.C
.MethodInfoTestStruct
*b
)
269 return (SimpleStruct
*) 0;
273 public void ToStringWithPointerSignaturesToNonPrimitiveType ()
275 Assert
.AreEqual ("SimpleStruct* PtrFunc2(SimpleStruct*, A.B.C.MethodInfoTestStruct*)",
276 this.GetType ().GetMethod ("PtrFunc2").ToString ());
279 public void ToStringGenericMethod ()
281 Assert
.AreEqual ("System.Collections.ObjectModel.ReadOnlyCollection`1[T] AsReadOnly[T](T[])",
282 typeof (Array
).GetMethod ("AsReadOnly").ToString ());
285 class GBD_A { public virtual void f () {}
}
286 class GBD_B
: GBD_A { public override void f () {}
}
287 class GBD_C
: GBD_B { public override void f () {}
}
288 class GBD_D
: GBD_C { public new virtual void f () {}
}
289 class GBD_E
: GBD_D { public override void f () {}
}
291 class GBD_E2
: GBD_D { }
292 class GBD_F
: GBD_E { }
296 public void GetBaseDefinition ()
298 Assert
.AreEqual (typeof (GBD_A
), typeof (GBD_C
).GetMethod ("f").GetBaseDefinition ().DeclaringType
);
299 Assert
.AreEqual (typeof (GBD_A
), typeof (GBD_C
).GetMethod ("f").GetBaseDefinition ().ReflectedType
, "#1r");
301 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_D
).GetMethod ("f").GetBaseDefinition ().DeclaringType
);
302 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_D
).GetMethod ("f").GetBaseDefinition ().ReflectedType
, "#2r");
304 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_E
).GetMethod ("f").GetBaseDefinition ().DeclaringType
);
305 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_E
).GetMethod ("f").GetBaseDefinition ().ReflectedType
, "#3r");
307 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_E2
).GetMethod ("f").GetBaseDefinition ().DeclaringType
, "#4");
308 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_E2
).GetMethod ("f").GetBaseDefinition ().ReflectedType
, "#4r");
310 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_F
).GetMethod ("f").GetBaseDefinition ().DeclaringType
, "#5");
311 Assert
.AreEqual (typeof (GBD_D
), typeof (GBD_F
).GetMethod ("f").GetBaseDefinition ().ReflectedType
, "#5r");
315 class GenericBase
<T
,H
> {
316 public virtual void f2 () { }
319 class GenericMid
<T
, U
> : GenericBase
<T
, Action
<U
>> {
320 public virtual T
f1 () { return default (T); }
323 class GenericChild
<T
> : GenericMid
<T
, int> {
324 public override T
f1 () { return default (T); }
325 public override void f2 () { }
328 class DerivedFromGenericBase
: GenericBase
<int, int> {
332 public void GetBaseDefinition_OpenConstructedBaseType () // 36305
334 var t
= typeof (GenericChild
<string>);
336 var mi1
= t
.GetMethod ("f1");
337 var mi1_base
= mi1
.GetBaseDefinition ();
339 Assert
.AreEqual (typeof (GenericMid
<string, int>), mi1_base
.DeclaringType
, "#1");
341 var mi2
= t
.GetMethod ("f2");
342 var mi2_base
= mi2
.GetBaseDefinition ();
344 Assert
.AreEqual (typeof (GenericBase
<string, Action
<int>>), mi2_base
.DeclaringType
, "#2");
347 class TestInheritedMethodA
{
348 private void TestMethod ()
352 public void TestMethod2 ()
357 class TestInheritedMethodB
: TestInheritedMethodA
{
361 public void InheritanceTestGetMethodTest ()
363 MethodInfo inheritedMethod
= typeof(TestInheritedMethodB
).GetMethod("TestMethod", BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
364 MethodInfo baseMethod
= typeof(TestInheritedMethodB
).GetMethod("TestMethod", BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
365 Assert
.AreSame (inheritedMethod
, baseMethod
);
367 MethodInfo inheritedMethod2
= typeof(TestInheritedMethodB
).GetMethod("TestMethod2", BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
368 MethodInfo baseMethod2
= typeof(TestInheritedMethodB
).GetMethod("TestMethod2", BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
369 Assert
.AreSame (inheritedMethod
, baseMethod
);
373 public void GetMethodBody_Abstract ()
375 MethodBody mb
= typeof (InterfaceTest
).GetMethod ("Clone").GetMethodBody ();
380 public void GetMethodBody_Runtime ()
382 MethodBody mb
= typeof (AsyncCallback
).GetMethod ("Invoke").GetMethodBody ();
387 public void GetMethodBody_Pinvoke ()
389 MethodBody mb
= typeof (MethodInfoTest
).GetMethod ("dllImportMethod").GetMethodBody ();
394 public void GetMethodBody_Icall ()
396 foreach (MethodInfo mi
in typeof (object).GetMethods (BindingFlags
.Public
|BindingFlags
.NonPublic
|BindingFlags
.Instance
))
397 if ((mi
.GetMethodImplementationFlags () & MethodImplAttributes
.InternalCall
) != 0) {
398 MethodBody mb
= mi
.GetMethodBody ();
403 public static void locals_method ()
405 byte[] b
= new byte [10];
408 /* This generates a pinned local */
409 fixed (byte *p
= &b
[0]) {
415 public void GetMethodBody ()
417 #if (MONOTOUCH || FULL_AOT_RUNTIME) && !DEBUG
418 Assert
.Ignore ("Release app (on devices) are stripped of (managed) IL so this test would fail");
420 MethodBody mb
= typeof (MethodInfoTest
).GetMethod ("locals_method").GetMethodBody ();
422 Assert
.IsTrue (mb
.InitLocals
, "#1");
423 Assert
.IsTrue (mb
.LocalSignatureMetadataToken
> 0, "#2");
425 IList
<LocalVariableInfo
> locals
= mb
.LocalVariables
;
427 bool foundPinnedBytePointer
= false;
429 foreach (LocalVariableInfo lvi
in locals
) {
430 if (lvi
.LocalType
== typeof (byte[]))
431 // This is optimized out by CSC in .NET 4.6
432 Assert
.IsFalse (lvi
.IsPinned
, "#3-1");
434 if (/* mcs */ lvi
.LocalType
== typeof (byte*) || /* csc */ lvi
.LocalType
== typeof (byte).MakeByRefType ()) {
435 // We have three locals. There's b the byte[], there's a byte* and there's a byte&.
436 // mcs emits a byte* for the latter type.
437 // We need to find one such pinned byte pointer. Therefore we're folding with logical or
438 foundPinnedBytePointer
= foundPinnedBytePointer
|| lvi
.IsPinned
;
442 Assert
.IsTrue (foundPinnedBytePointer
, "#4");
445 public int return_parameter_test ()
451 public void GetMethodFromHandle_Generic ()
453 MethodHandleTest
<int> test
= new MethodHandleTest
<int> ();
454 RuntimeMethodHandle mh
= test
.GetType ().GetProperty ("MyList")
455 .GetGetMethod ().MethodHandle
;
456 MethodBase mb
= MethodInfo
.GetMethodFromHandle (mh
,
457 typeof (MethodHandleTest
<int>).TypeHandle
);
458 Assert
.IsNotNull (mb
, "#1");
459 List
<int> list
= (List
<int>) mb
.Invoke (test
, null);
460 Assert
.IsNotNull (list
, "#2");
461 Assert
.AreEqual (1, list
.Count
, "#3");
465 public void ReturnParameter ()
467 ParameterInfo pi
= typeof (MethodInfoTest
).GetMethod ("return_parameter_test").ReturnParameter
;
468 Assert
.AreEqual (typeof (int), pi
.ParameterType
, "#1");
469 Assert
.AreEqual (-1, pi
.Position
, "#2");
470 // MS always return false here
471 //Assert.IsTrue (pi.IsRetval, "#3");
475 public void MethodInfoModule ()
477 Type type
= typeof (MethodInfoTest
);
478 MethodInfo me
= type
.GetMethod ("return_parameter_test");
480 Assert
.AreEqual (type
.Module
, me
.Module
);
484 public void InvokeOnRefOnlyAssembly ()
486 Assembly a
= Assembly
.ReflectionOnlyLoad (typeof (MethodInfoTest
).Assembly
.FullName
);
487 Type t
= a
.GetType (typeof (RefOnlyMethodClass
).FullName
);
488 MethodInfo m
= t
.GetMethod ("RefOnlyMethod", BindingFlags
.Static
| BindingFlags
.NonPublic
);
490 m
.Invoke (null, new object [0]);
492 } catch (InvalidOperationException ex
) {
493 // The requested operation is invalid in the
494 // ReflectionOnly context
495 Assert
.AreEqual (typeof (InvalidOperationException
), ex
.GetType (), "#2");
496 Assert
.IsNull (ex
.InnerException
, "#3");
497 Assert
.IsNotNull (ex
.Message
, "#4");
502 [ExpectedException (typeof (TargetInvocationException
))]
503 public void InvokeInvalidOpExceptionThrow () {
504 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("ThrowMethod");
505 mi
.Invoke(null, null);
508 public static void ThrowMethod () {
509 throw new InvalidOperationException ();
513 public void InvokeGenericVtype ()
515 KeyValuePair
<string, uint> kvp
= new KeyValuePair
<string, uint> ("a", 21);
516 Type type
= kvp
.GetType ();
517 Type
[] arguments
= type
.GetGenericArguments ();
518 MethodInfo method
= typeof (MethodInfoTest
).GetMethod ("Go");
519 MethodInfo generic_method
= method
.MakeGenericMethod (arguments
);
520 kvp
= (KeyValuePair
<string, uint>)generic_method
.Invoke (null, new object [] { kvp }
);
522 Assert
.AreEqual ("a", kvp
.Key
, "#1");
523 Assert
.AreEqual (21, kvp
.Value
, "#2");
526 public static KeyValuePair
<T1
, T2
> Go
<T1
, T2
> (KeyValuePair
<T1
, T2
> kvp
)
532 public void InvokeGenericInst ()
534 List
<string> str
= null;
536 object [] methodArgs
= new object [] { str }
;
537 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("GenericRefMethod");
538 mi
.Invoke (null, methodArgs
);
539 Assert
.IsNotNull (methodArgs
[0], "#A1");
540 Assert
.IsNull (str
, "#A2");
541 Assert
.IsTrue (methodArgs
[0] is List
<string>, "#A3");
543 List
<string> refStr
= methodArgs
[0] as List
<string>;
544 Assert
.IsNotNull (refStr
, "#B1");
545 Assert
.AreEqual (1, refStr
.Count
, "#B2");
546 Assert
.AreEqual ("test", refStr
[0], "#B3");
549 public static void GenericRefMethod (ref List
<string> strArg
)
551 strArg
= new List
<string> ();
555 public void MakeGenericMethodArgsMismatchFoo
<T
> ()
560 public void MakeGenericMethodArgsMismatch ()
562 MethodInfo gmi
= this.GetType ().GetMethod (
563 "MakeGenericMethodArgsMismatchFoo");
565 gmi
.MakeGenericMethod ();
567 } catch (ArgumentException ex
) {
568 // The type or method has 1 generic parameter(s),
569 // but 0 generic argument(s) were provided. A
570 // generic argument must be provided for each
572 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#2");
573 Assert
.IsNull (ex
.InnerException
, "#3");
574 Assert
.IsNotNull (ex
.Message
, "#4");
575 Assert
.IsNull (ex
.ParamName
, "#5");
579 public void SimpleGenericMethod
<TFoo
, TBar
> () {}
582 public void MakeGenericMethodWithNullArray ()
584 MethodInfo gmi
= this.GetType ().GetMethod ("SimpleGenericMethod");
586 gmi
.MakeGenericMethod ((Type
[]) null);
588 } catch (ArgumentNullException ex
) {
589 Assert
.AreEqual (typeof (ArgumentNullException
), ex
.GetType (), "#2");
590 Assert
.IsNull (ex
.InnerException
, "#3");
591 Assert
.IsNotNull (ex
.Message
, "#4");
592 Assert
.AreEqual ("methodInstantiation", ex
.ParamName
, "#5");
597 public void MakeGenericMethodWithNullValueInTypesArray ()
599 MethodInfo gmi
= this.GetType ().GetMethod ("SimpleGenericMethod");
601 gmi
.MakeGenericMethod (new Type
[] { typeof (int), null }
);
603 } catch (ArgumentNullException ex
) {
604 Assert
.AreEqual (typeof (ArgumentNullException
), ex
.GetType (), "#2");
605 Assert
.IsNull (ex
.InnerException
, "#3");
606 Assert
.IsNotNull (ex
.Message
, "#4");
607 Assert
.IsNull (ex
.ParamName
, "#5");
612 public void MakeGenericMethodWithNonGenericMethodDefinitionMethod ()
614 MethodInfo gmi
= this.GetType ().GetMethod ("SimpleGenericMethod");
615 MethodInfo inst
= gmi
.MakeGenericMethod (typeof (int), typeof (double));
617 inst
.MakeGenericMethod (typeof (int), typeof (double));
619 } catch (InvalidOperationException ex
) {
622 #if !MONOTOUCH && !FULL_AOT_RUNTIME
623 public TFoo SimpleGenericMethod2
<TFoo
, TBar
> () { return default (TFoo); }
624 /*Test for the uggly broken behavior of SRE.*/
626 public void MakeGenericMethodWithSreTypeResultsInStupidMethodInfo ()
628 AssemblyName assemblyName
= new AssemblyName ();
629 assemblyName
.Name
= "MonoTests.System.Reflection.Emit.MethodInfoTest";
630 AssemblyBuilder assembly
= Thread
.GetDomain ().DefineDynamicAssembly (assemblyName
, AssemblyBuilderAccess
.RunAndSave
, ".");
631 ModuleBuilder module
= assembly
.DefineDynamicModule ("module1", "tst.dll");
632 TypeBuilder tb
= module
.DefineType ("Test", TypeAttributes
.Public
);
634 MethodInfo gmi
= this.GetType ().GetMethod ("SimpleGenericMethod2");
635 MethodInfo ins
= gmi
.MakeGenericMethod (typeof (int), tb
);
637 Assert
.AreSame (tb
, ins
.GetGenericArguments () [1], "#1");
638 /*broken ReturnType*/
639 Assert
.AreSame (gmi
.GetGenericArguments () [0], ins
.ReturnType
, "#2");
642 public static int? pass_nullable (int? i
)
648 public void NullableTests ()
650 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("pass_nullable");
651 Assert
.AreEqual (102, mi
.Invoke (null, new object [] { 102 }
), "#1");
652 Assert
.AreEqual (null, mi
.Invoke (null, new object [] { null }
), "#2");
654 // Test conversion of vtype to a nullable type for the this argument
655 PropertyInfo pi
= typeof (Nullable
<int>).GetProperty ("HasValue");
656 Assert
.AreEqual (true, pi
.GetGetMethod ().Invoke (10, null));
657 PropertyInfo pi2
= typeof (Nullable
<int>).GetProperty ("Value");
658 Assert
.AreEqual (10, pi2
.GetGetMethod ().Invoke (10, null));
662 public void NullableTestsStatic ()
664 Nullable
<Double
> val
= new Nullable
<Double
>(new Double());
665 MethodInfo mi
= typeof (Nullable
<Double
>).GetMethod ("op_Implicit");
667 mi
.Invoke(null, new[] { obj }
);
670 public static void foo_generic
<T
> ()
675 public void IsGenericMethod ()
677 MethodInfo mi
= typeof (MethodInfoTest
).GetMethod ("foo_generic");
678 Assert
.AreEqual (true, mi
.IsGenericMethod
, "#1");
679 MethodInfo mi2
= mi
.MakeGenericMethod (new Type
[] { typeof (int) }
);
680 Assert
.AreEqual (true, mi2
.IsGenericMethod
, "#2");
681 MethodInfo mi3
= typeof (GenericHelper
<int>).GetMethod ("Test");
682 Assert
.AreEqual (false, mi3
.IsGenericMethod
, "#3");
687 public static void Foo
<T2
> (T2 i
)
691 public static void Bar ()
697 public static void Baz ()
704 public void ContainsGenericParameters ()
706 // Non-generic method in open generic type
707 Assert
.IsTrue (typeof (A
<int>).GetGenericTypeDefinition ().GetMethod ("Bar").ContainsGenericParameters
);
708 // open generic method in closed generic type
709 Assert
.IsTrue (typeof (A
<int>).GetMethod ("Foo").ContainsGenericParameters
);
710 // non-generic method in closed generic type
711 Assert
.IsFalse (typeof (A
<int>).GetMethod ("Bar").ContainsGenericParameters
);
712 // closed generic method in closed generic type
713 Assert
.IsFalse (typeof (A
<int>).GetMethod ("Foo").MakeGenericMethod (new Type
[] { typeof (int) }
).ContainsGenericParameters
);
714 // non-generic method in non-generic nested type of closed generic type
715 Assert
.IsFalse (typeof (A
<int>.B
).GetMethod ("Baz").ContainsGenericParameters
);
716 // non-generic method in non-generic nested type of open generic type
717 Assert
.IsTrue (typeof (A
<int>.B
).GetGenericTypeDefinition ().GetMethod ("Baz").ContainsGenericParameters
);
721 public void IsGenericMethodDefinition ()
723 MethodInfo m1
= typeof (A
<>).GetMethod ("Foo");
724 Assert
.IsTrue (m1
.IsGenericMethod
, "#A1");
725 Assert
.IsTrue (m1
.IsGenericMethodDefinition
, "#A2");
727 MethodInfo m2
= typeof (A
<int>).GetMethod ("Foo");
728 Assert
.IsTrue (m2
.IsGenericMethod
, "#B1");
729 Assert
.IsTrue (m2
.IsGenericMethodDefinition
, "#B2");
731 MethodInfo m3
= m2
.MakeGenericMethod (typeof (int));
732 Assert
.IsTrue (m3
.IsGenericMethod
, "#C1");
733 Assert
.IsFalse (m3
.IsGenericMethodDefinition
, "#C2");
737 public void GetGenericMethodDefinition ()
739 MethodInfo mi1
= typeof (MyList
<>).GetMethod ("ConvertAll");
740 MethodInfo mi2
= typeof (MyList
<int>).GetMethod ("ConvertAll");
742 Assert
.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[T,TOutput]",
743 mi1
.GetParameters () [0].ParameterType
.ToString (), "#A1");
744 Assert
.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[System.Int32,TOutput]",
745 mi2
.GetParameters () [0].ParameterType
.ToString (), "#A2");
746 Assert
.IsTrue (mi1
.IsGenericMethod
, "#A3");
747 Assert
.IsTrue (mi1
.IsGenericMethodDefinition
, "#A4");
748 Assert
.IsTrue (mi2
.IsGenericMethod
, "#A5");
749 Assert
.IsTrue (mi2
.IsGenericMethodDefinition
, "#A6");
751 MethodInfo mi3
= mi2
.GetGenericMethodDefinition ();
753 Assert
.IsTrue (mi3
.IsGenericMethod
, "#B1");
754 Assert
.IsTrue (mi3
.IsGenericMethodDefinition
, "#B2");
755 Assert
.AreSame (mi2
, mi3
, "#B3");
757 MethodInfo mi4
= mi2
.MakeGenericMethod (typeof (short));
758 Assert
.IsTrue (mi4
.IsGenericMethod
, "#C1");
759 Assert
.IsFalse (mi4
.IsGenericMethodDefinition
, "#C2");
760 Assert
.AreSame (mi2
, mi4
.GetGenericMethodDefinition (), "#C3");
763 public void TestMethod123(int a
, int b
) {}
766 public void GetParametersDontReturnInternedArray ()
768 var method
= typeof (MethodInfoTest
).GetMethod ("TestMethod123");
769 var parms
= method
.GetParameters ();
770 Assert
.AreNotSame (parms
, method
.GetParameters (), "#1");
773 Assert
.IsNotNull (method
.GetParameters () [0], "#2");
777 public void Bug354757 ()
779 MethodInfo gmd
= (typeof (MyList
<int>)).GetMethod ("ConvertAll");
780 MethodInfo oi
= gmd
.MakeGenericMethod (gmd
.GetGenericArguments ());
781 Assert
.AreSame (gmd
, oi
);
785 [ExpectedException (typeof (ArgumentException
))]
787 [Category ("NotWorking")] // #10552
789 public void MakeGenericMethodRespectConstraints ()
791 var m
= typeof (MethodInfoTest
).GetMethod ("TestMethod");
792 m
.MakeGenericMethod (typeof (Type
));
795 public void TestMethod
<T
> () where T
: Exception
799 public class MyList
<T
>
801 public TOutput ConvertAll
<TOutput
> (Foo
<T
,TOutput
> arg
)
803 return default (TOutput
);
805 public T
ConvertAll2 (MyList
<T
> arg
)
811 public class Foo
<T
,TOutput
>
815 class GenericHelper
<T
>
817 public void Test (T t
)
821 interface IMethodInvoke
<out T
>
826 class MethodInvoke
: IMethodInvoke
<string>
828 public string Test ()
830 return "MethodInvoke";
835 public void GetInterfaceMapWorksWithVariantIfaces ()
837 var m0
= typeof (IMethodInvoke
<object>).GetMethod ("Test");
838 var m1
= typeof (IMethodInvoke
<string>).GetMethod ("Test");
839 var obj
= new MethodInvoke ();
841 Assert
.AreEqual ("MethodInvoke", m0
.Invoke (obj
, new Object
[0]));
842 Assert
.AreEqual ("MethodInvoke", m1
.Invoke (obj
, new Object
[0]));
846 public int? Bug12856 ()
852 public void MethodToStringShouldPrintFullNameOfGenericStructs ()
854 var m
= GetType ().GetMethod ("Bug12856");
855 Assert
.AreEqual ("System.Nullable`1[System.Int32] Bug12856()", m
.ToString (), "#1");
859 public void GetReflectedType () // #12205
861 // public method declared in base type, queried from a derived type
862 MethodInfo mi
= typeof (TestInheritedMethodB
).GetMethod ("TestMethod2");
863 Assert
.AreEqual (mi
.ReflectedType
, typeof (TestInheritedMethodB
), "#1");
865 // public method declared in a generic class,
866 // queried from a non-generic class derived
867 // from an instantiation of the generic class.
868 mi
= typeof (DerivedFromGenericBase
).GetMethod ("f2");
869 Assert
.AreEqual (mi
.ReflectedType
, typeof (DerivedFromGenericBase
), "#2");
871 // public method declared in a generic class,
872 // queried from the generic type defintion of
873 // a generic derived class.
874 mi
= typeof (GenericMid
<,>).GetMethod ("f2");
875 Assert
.AreEqual (mi
.ReflectedType
, typeof (GenericMid
<,>), "#3");
877 // public method declared in a generic class,
878 // queried from an instantiation of a generic
880 mi
= typeof (GenericMid
<int,int>).GetMethod ("f2");
881 Assert
.AreEqual (mi
.ReflectedType
, typeof (GenericMid
<int,int>), "#4");
885 #if !MONOTOUCH && !FULL_AOT_RUNTIME
886 class GenericClass
<T
>
888 public void Method ()
891 Console
.WriteLine(lv
);
894 public void Method2
<K
> (T a0
, K a1
)
898 Console
.WriteLine (var0
);
899 Console
.WriteLine (var1
);
903 static void EnsureMethodExists (Type type
, string name
, params Type
[] parameterTypes
)
905 var method
= type
.GetTypeInfo ().GetDeclaredMethods (name
)
906 .SingleOrDefault (m
=> m
.GetParameters ().Select (p
=> p
.ParameterType
).SequenceEqual (parameterTypes
));
907 Assert
.IsNotNull (method
, $"{type}.{name}");
910 public void EnsureEntityFrameworkMethodsExist ()
912 // EntityFramework6 relies on the following methods
913 // see https://github.com/aspnet/EntityFramework6/blob/master/src/EntityFramework/Core/Objects/ELinq/MethodCallTranslator.cs#L846
914 // also https://github.com/mono/mono/pull/10452
915 EnsureMethodExists (typeof (Math
), "Ceiling", typeof (decimal));
916 EnsureMethodExists (typeof (Math
), "Ceiling", typeof (double));
917 EnsureMethodExists (typeof (Math
), "Floor", typeof (decimal));
918 EnsureMethodExists (typeof (Math
), "Floor", typeof (double));
919 EnsureMethodExists (typeof (Math
), "Round", typeof (decimal));
920 EnsureMethodExists (typeof (Math
), "Round", typeof (double));
921 EnsureMethodExists (typeof (Math
), "Round", typeof (decimal), typeof (int));
922 EnsureMethodExists (typeof (Math
), "Round", typeof (double), typeof (int));
923 EnsureMethodExists (typeof (Decimal
), "Floor", typeof (decimal));
924 EnsureMethodExists (typeof (Decimal
), "Ceiling", typeof (decimal));
925 EnsureMethodExists (typeof (Decimal
), "Round", typeof (decimal));
926 EnsureMethodExists (typeof (Decimal
), "Round", typeof (decimal), typeof (int));
927 EnsureMethodExists (typeof (String
), "Replace", typeof (String
), typeof (String
));
928 EnsureMethodExists (typeof (String
), "ToLower");
929 EnsureMethodExists (typeof (String
), "ToUpper");
930 EnsureMethodExists (typeof (String
), "Trim");
931 EnsureMethodExists (typeof (Math
), "Truncate", typeof (decimal));
932 EnsureMethodExists (typeof (Math
), "Truncate", typeof (double));
933 EnsureMethodExists (typeof (Math
), "Pow", typeof (double), typeof (double));
934 EnsureMethodExists (typeof (Guid
), "NewGuid");
935 EnsureMethodExists (typeof (String
), "Contains", typeof (string));
936 EnsureMethodExists (typeof (String
), "IndexOf", typeof (string));
937 EnsureMethodExists (typeof (String
), "StartsWith", typeof (string));
938 EnsureMethodExists (typeof (String
), "EndsWith", typeof (string));
939 EnsureMethodExists (typeof (String
), "Substring", typeof (int));
940 EnsureMethodExists (typeof (String
), "Substring", typeof (int), typeof (int));
941 EnsureMethodExists (typeof (String
), "Remove", typeof (int));
942 EnsureMethodExists (typeof (String
), "Remove", typeof (int), typeof (int));
943 EnsureMethodExists (typeof (String
), "IsNullOrEmpty", typeof (string));
944 EnsureMethodExists (typeof (String
), "Concat", typeof (string), typeof (string));
945 EnsureMethodExists (typeof (String
), "Concat", typeof (string), typeof (string), typeof (string));
946 EnsureMethodExists (typeof (String
), "Concat", typeof (string), typeof (string), typeof (string), typeof (string));
947 EnsureMethodExists (typeof (String
), "Concat", typeof (object), typeof (object));
948 EnsureMethodExists (typeof (String
), "Concat", typeof (object), typeof (object), typeof (object));
949 EnsureMethodExists (typeof (String
), "Concat", typeof (object), typeof (object), typeof (object), typeof (object));
950 EnsureMethodExists (typeof (String
), "Concat", typeof (object[]));
951 EnsureMethodExists (typeof (String
), "Concat", typeof (string[]));
952 EnsureMethodExists (typeof (String
), "Trim", typeof (Char
[]));
953 EnsureMethodExists (typeof (String
), "TrimStart", typeof (Char
[]));
954 EnsureMethodExists (typeof (String
), "TrimEnd", typeof (Char
[]));
958 public void TestLocalVariableTypes ()
960 var typeofT
= typeof (GenericClass
<>).GetGenericArguments () [0];
961 var typeofK
= typeof (GenericClass
<>).GetMethod ("Method2").GetGenericArguments () [0];
963 var type
= typeof (GenericClass
<>).GetMethod("Method").GetMethodBody().LocalVariables
[0].LocalType
;
964 Assert
.AreEqual (typeofT
, type
);
965 Assert
.AreEqual (typeof (GenericClass
<>), type
.DeclaringType
);
967 bool foundTypeOfK
= false;
968 bool foundExpectedType
= false;
970 MethodBody mb
= typeof (GenericClass
<>).GetMethod("Method2").GetMethodBody();
971 foreach (LocalVariableInfo lvi
in mb
.LocalVariables
) {
972 if (lvi
.LocalType
== typeofK
) {
974 Assert
.AreEqual (typeof (GenericClass
<>), lvi
.LocalType
.DeclaringType
, "#1-1");
975 } else if (lvi
.LocalType
== typeofT
) {
976 foundExpectedType
= true;
977 Assert
.AreEqual (typeof (GenericClass
<>), lvi
.LocalType
.DeclaringType
, "#1-2");
981 Assert
.IsTrue (foundTypeOfK
, "#1-3");
982 if (mb
.LocalVariables
.Count
< 2)
983 Assert
.Ignore ("Code built in release mode - 'T var0' optmized out");
985 Assert
.IsTrue (foundExpectedType
, "#1-4");
987 foundTypeOfK
= false;
988 foundExpectedType
= false;
989 mb
= typeof (GenericClass
<int>).GetMethod("Method2").GetMethodBody();
990 foreach (LocalVariableInfo lvi
in mb
.LocalVariables
) {
991 if (lvi
.LocalType
== typeofK
) {
993 Assert
.AreEqual (typeof (GenericClass
<>), lvi
.LocalType
.DeclaringType
, "#2-1");
994 } else if (lvi
.LocalType
== typeof (int)) {
995 foundExpectedType
= true;
999 Assert
.IsTrue (foundTypeOfK
, "#2-3");
1000 if (mb
.LocalVariables
.Count
< 2)
1001 Assert
.Ignore ("Code built in release mode - 'int var0' optmized out");
1003 Assert
.IsTrue (foundExpectedType
, "#2-4");
1009 class RefOnlyMethodClass
1011 // Helper static method
1012 static void RefOnlyMethod ()
1017 public class MethodHandleTest
<T
>
1019 private List
<T
> _myList
= new List
<T
> ();
1021 public MethodHandleTest ()
1023 _myList
.Add (default (T
));
1026 public List
<T
> MyList
{
1027 get { return _myList; }
1028 set { _myList = value; }