2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / corlib / Test / System.Reflection / BinderTests.cs
1 //
2 // System.Reflection.BinderTests - Tests Type.DefaultBinder
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (c) 2004 Novell, Inc. (http://www.novell.com)
8 //
9
10 using NUnit.Framework;
11 using System;
12 using System.Globalization;
13 using System.IO;
14 using System.Reflection;
15
16 namespace MonoTests.System.Reflection
17 {
18         enum MyEnum {
19                 Zero,
20                 One,
21                 Two
22         }
23         
24         class SampleClass {
25                 public static void SampleMethod (object o) { }
26
27                 public Type this[decimal i] {
28                         get { return i.GetType (); }
29                 }
30
31                 public Type this[object i] {
32                         get { return i.GetType (); }
33                 }
34
35         }
36         
37         class SingleIndexer {
38                 public Type this [int i] {
39                         get { return i.GetType (); }
40                 }
41         }
42         
43         class MultiIndexer
44         {
45                 public Type this[byte i] {
46                         get { return i.GetType (); }
47                 }
48
49                 public Type this[sbyte i] {
50                         get { return i.GetType (); }
51                 }
52
53                 public Type this[short i] {
54                         get { return i.GetType (); }
55                 }
56
57                 public Type this[ushort i] {
58                         get { return i.GetType (); }
59                 }
60
61                 public Type this[int i] {
62                         get { return i.GetType (); }
63                 }
64
65                 public Type this[uint i] {
66                         get { return i.GetType (); }
67                 }
68
69                 public Type this[long i] {
70                         get { return i.GetType (); }
71                 }
72
73                 public Type this[ulong i] {
74                         get { return i.GetType (); }
75                 }
76
77                 public Type this[float i] {
78                         get { return i.GetType (); }
79                 }
80
81                 public Type this[double i] {
82                         get { return i.GetType (); }
83                 }
84
85                 public Type this[decimal i] {
86                         get { return i.GetType (); }
87                 }
88
89                 public Type this[object i] {
90                         get { return i.GetType (); }
91                 }
92
93                 public Type this[Enum i] {
94                         get { return i.GetType (); }
95                 }
96         }
97
98         [TestFixture]
99         public class BinderTest
100         {
101                 Binder binder = Type.DefaultBinder;
102
103                 [Test]
104                 [ExpectedException (typeof (ArgumentException))]
105                 public void SelectPropertyTestNull1 ()
106                 {
107                         // The second argument is the one
108                         binder.SelectProperty (0, null, null, null, null);
109                 }
110
111                 [Test]
112                 [ExpectedException (typeof (ArgumentException))]
113                 public void SelectPropertyTestEmpty ()
114                 {
115                         // The second argument is the one
116                         binder.SelectProperty (0, new PropertyInfo [] {}, null, null, null);
117                 }
118
119                 [Test]
120                 [ExpectedException (typeof (AmbiguousMatchException))]
121                 public void AmbiguousProperty1 () // Bug 58381
122                 {
123                         Type type = typeof (MultiIndexer);
124                         PropertyInfo pi = type.GetProperty ("Item");
125                 }
126
127                 [Test]
128                 public void SelectAndInvokeAllProperties1 ()
129                 {
130                         Type type = typeof (MultiIndexer);
131                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
132                                                                     BindingFlags.Public |
133                                                                     BindingFlags.Instance);
134
135                         // These don't cause an AmbiguousMatchException
136                         Type [] types = { typeof (byte), typeof (short),
137                                           typeof (int), typeof (long),
138                                           typeof (MyEnum) };
139
140                         /* MS matches short for sbyte!!! */
141                         /* MS matches int for ushort!!! */
142                         /* MS matches long for uint!!! */
143                         /** These do weird things under MS if used together and then in separate arrays *
144                         Type [] types = { typeof (ulong), typeof (float), typeof (double),
145                                           typeof (decimal), typeof (object) };
146                         */
147
148                         MultiIndexer obj = new MultiIndexer ();
149
150                         foreach (Type t in types) {
151                                 PropertyInfo prop = null;
152                                 try {
153                                         prop = binder.SelectProperty (0, props, null, new Type [] {t}, null);
154                                 } catch (Exception e) {
155                                         throw new Exception ("Type: " + t, e);
156                                 }
157                                 Type gotten = (Type) prop.GetValue (obj, new object [] {Activator.CreateInstance (t)});
158                                 Assert.AreEqual (t, gotten);
159                         }
160                 }
161
162                 [Test]
163                 public void SelectAndInvokeAllProperties2 ()
164                 {
165                         Type type = typeof (MultiIndexer);
166                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
167                                                                     BindingFlags.Public |
168                                                                     BindingFlags.Instance);
169
170                         Type [] types = { typeof (ushort), typeof (char) };
171
172                         MultiIndexer obj = new MultiIndexer ();
173                         PropertyInfo prop1 = binder.SelectProperty (0, props, null, new Type [] {types [0]}, null);
174                         PropertyInfo prop2 = binder.SelectProperty (0, props, null, new Type [] {types [1]}, null);
175                         Assert.AreEqual (prop1, prop2);
176                 }
177
178                 [Test]
179                 public void Select1Match2 ()
180                 {
181                         Type type = typeof (SingleIndexer);
182                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
183                                                                     BindingFlags.Public |
184                                                                     BindingFlags.Instance);
185                         PropertyInfo prop = binder.SelectProperty (0, props, null, new Type [0], null);
186                         Assert.IsNull (prop, "empty");
187                 }
188                 
189                 [Test]
190                 public void Select1Match ()
191                 {
192                         Type type = typeof (SingleIndexer);
193                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
194                                                                     BindingFlags.Public |
195                                                                     BindingFlags.Instance);
196
197                         PropertyInfo prop;
198                         
199                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (long) }, null);
200                         Assert.IsNull (prop, "long");
201                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (int) }, null);
202                         Assert.IsNotNull (prop, "int");
203                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (short) }, null);
204                         Assert.IsNotNull (prop, "short");
205                 }
206
207                 [Test]
208                 public void SelectMethod_ByRef ()
209                 {
210                         Type type = typeof (ByRefMatch);
211                         BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance;
212                         MethodBase [] match;
213                         Type [] types;
214                         MethodBase selected;
215
216                         MethodInfo mi_run = type.GetMethod ("Run", flags, binder,
217                                 new Type [] { typeof (int) }, null);
218                         Assert.IsFalse (mi_run.GetParameters () [0].ParameterType.IsByRef, "#A1");
219                         MethodInfo mi_run_ref = type.GetMethod ("Run", flags, binder,
220                                 new Type [] { typeof (int).MakeByRefType () }, null);
221                         Assert.IsTrue (mi_run_ref.GetParameters () [0].ParameterType.IsByRef, "#A2");
222
223                         match = new MethodBase [] { mi_run_ref };
224                         types = new Type [] { typeof (int) };
225                         selected = binder.SelectMethod (flags, match, types, null);
226                         Assert.IsNull (selected, "#B1");
227                         types = new Type [] { typeof (int).MakeByRefType () };
228                         selected = binder.SelectMethod (flags, match, types, null);
229                         Assert.AreSame (mi_run_ref, selected, "#B2");
230
231                         match = new MethodBase [] { mi_run };
232                         types = new Type [] { typeof (int) };
233                         selected = binder.SelectMethod (flags, match, types, null);
234                         Assert.AreSame (mi_run, selected, "#C1");
235                         types = new Type [] { typeof (int).MakeByRefType () };
236                         selected = binder.SelectMethod (flags, match, types, null);
237                         Assert.IsNull (selected, "#C1");
238
239                         match = new MethodBase [] { mi_run, mi_run_ref };
240                         types = new Type [] { typeof (int) };
241                         selected = binder.SelectMethod (flags, match, types, null);
242                         Assert.AreSame (mi_run, selected, "#D1");
243                         types = new Type [] { typeof (int).MakeByRefType () };
244                         selected = binder.SelectMethod (flags, match, types, null);
245                         Assert.AreSame (mi_run_ref, selected, "#D2");
246                 }
247
248                 [Test]
249                 public void ArgNullOnMethod () // see bug 58846. We throwed nullref here.
250                 {
251                         Type type = typeof (SampleClass);
252                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod;
253                         type.InvokeMember ("SampleMethod", flags, null, null, new object[] { null });
254                 }
255
256                 [Test]
257                 public void ArgNullOnProperty ()
258                 {
259                         Type type = typeof (SampleClass);
260                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
261                                                                     BindingFlags.Public |
262                                                                     BindingFlags.Instance);
263
264                         PropertyInfo prop = binder.SelectProperty (0, props, null, new Type [] {null}, null);
265                         Assert.IsNotNull (prop);
266                 }
267
268                 [Test]
269                 public void BindToMethod_ByRef ()
270                 {
271                         Type type = typeof (ByRefMatch);
272                         BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance;
273                         MethodBase [] match;
274                         object [] args = new object [] { 5 };
275                         object state;
276                         MethodBase selected;
277                         CultureInfo culture = CultureInfo.InvariantCulture;
278
279                         MethodInfo mi_run = type.GetMethod ("Run", flags, binder,
280                                 new Type [] { typeof (int) }, null);
281                         Assert.IsFalse (mi_run.GetParameters () [0].ParameterType.IsByRef, "#A1");
282                         MethodInfo mi_run_ref = type.GetMethod ("Run", flags, binder,
283                                 new Type [] { typeof (int).MakeByRefType () }, null);
284                         Assert.IsTrue (mi_run_ref.GetParameters () [0].ParameterType.IsByRef, "#A2");
285
286                         match = new MethodBase [] { mi_run };
287                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
288                                 null, out state);
289                         Assert.AreSame (mi_run, selected, "#1");
290
291                         match = new MethodBase [] { mi_run_ref };
292                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
293                                 null, out state);
294                         Assert.AreSame (mi_run_ref, selected, "#2");
295
296                         match = new MethodBase [] { mi_run, mi_run_ref };
297                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
298                                 null, out state);
299                         Assert.AreSame (mi_run, selected, "#3");
300
301                         match = new MethodBase [] { mi_run_ref, mi_run };
302                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
303                                 null, out state);
304                         Assert.AreSame (mi_run, selected, "#4");
305                 }
306
307                 [Test] // bug #41691
308                 public void BindToMethodNamedArgs ()
309                 {
310                         Type t = typeof (Bug41691);
311
312                         StringWriter sw = new StringWriter ();
313                         sw.NewLine = "\n";
314
315                         object[] argValues = new object [] {"Hello", "World", "Extra", sw};
316                         string [] argNames = new string [] {"firstName", "lastName"};
317
318                         t.InvokeMember ("PrintName",
319                                         BindingFlags.InvokeMethod,
320                                         null,
321                                         null,
322                                         argValues,
323                                         null,
324                                         null,
325                                         argNames);
326
327                         Assert.AreEqual ("Hello\nExtra\nWorld\n", sw.ToString ());
328                 }
329
330                 public class Bug41691
331                 {
332                         public static void PrintName (string lastName, string firstName, string extra, TextWriter output)
333                         {
334                                 output.WriteLine (firstName);
335                                 output.WriteLine (extra);
336                                 output.WriteLine (lastName);
337                         }
338                 }
339
340                 [Test] // bug #42457
341                 public void GetMethodAmbiguity ()
342                 {
343                         object IntegerObject = 5;
344                         object IntArrayObject = new int[] {5, 2, 5};
345                         object StringArrayObject = new string [] {"One", "Two"};
346                         object [] IntParam = new object [] {IntegerObject};
347                         object [] IntArrayParam = new object [] {IntArrayObject};
348                         object [] StringArrayParam = new object [] {StringArrayObject};
349
350                         object be = this;
351                         Type betype = this.GetType ();
352
353                         string name1 = "Bug42457Method";
354                         string name2 = "Bug42457Method2";
355
356                         MethodInfo mi_obj = betype.GetMethod (name1, Type.GetTypeArray (IntParam));
357                         mi_obj.Invoke (be, IntParam);
358                         Assert.AreEqual (1, bug42457, "#1");
359                         MethodInfo mi_arr = betype.GetMethod (name1, Type.GetTypeArray (IntArrayParam));
360                         mi_arr.Invoke (be, IntArrayParam);
361                         Assert.AreEqual (2, bug42457, "#2");
362                         MethodInfo mi_str = betype.GetMethod (name1, Type.GetTypeArray (StringArrayParam));
363                         mi_str.Invoke (be, StringArrayParam);
364                         Assert.AreEqual (3, bug42457, "#3");
365
366                         MethodInfo m2_obj = betype.GetMethod (name2, Type.GetTypeArray (IntParam));
367                         m2_obj.Invoke (be, IntParam);
368                         Assert.AreEqual (1, bug42457_2, "#4");
369                         MethodInfo m2_arr = betype.GetMethod (name2, Type.GetTypeArray (IntArrayParam));
370                         m2_arr.Invoke (be, IntArrayParam);
371                         Assert.AreEqual (2, bug42457_2, "#5");
372                         MethodInfo m2_str = betype.GetMethod (name2, Type.GetTypeArray(StringArrayParam));
373                         m2_str.Invoke (be, StringArrayParam);
374                         Assert.AreEqual (3, bug42457_2, "#6");
375                 }
376
377 #if NET_2_0
378                 [Test]
379                 public void NullableArg () {
380                         MethodInfo method = (typeof (BinderTest)).GetMethod("SetA", new [] {typeof (Int32)});
381                         Assert.AreEqual (5, method.Invoke (new BinderTest (), new object [] { 5 }));
382                 }
383
384                 public int SetA(Int32? a) {
385                         return (int)a;
386                 }
387 #endif
388
389                 static void MethodWithLongParam(long param)
390                 {
391                 }
392
393                 [Test]
394                 public void TestParamsAttribute ()
395                 {
396                         MethodInfo mi = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static|BindingFlags.Public, null, new Type [] { typeof (object), typeof (object) }, null);
397                         Assert.AreEqual (typeof (object), mi.GetParameters ()[1].ParameterType);
398
399                         MethodInfo mi2 = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static|BindingFlags.Public, null, new Type [] { typeof (object), typeof (object), typeof (object) }, null);
400                         Assert.AreEqual (typeof (object[]), mi2.GetParameters ()[1].ParameterType);
401                 }
402
403                 public static void params_method1 (object o, params object[] o2) {
404                 }
405
406                 public static void params_method1 (object o, object o2) {
407                 }
408
409                 public static double DoubleMethod (double d) {
410                         return d;
411                 }
412
413                 public static float FloatMethod (float f) {
414                         return f;
415                 }
416
417                 [Test]
418                 public void ChangeType ()
419                 {
420                         // Char -> Double
421                         Assert.AreEqual (42.0, typeof (BinderTest).GetMethod ("DoubleMethod").Invoke (null, new object[] { (char)42 }));
422
423                         // Char -> Float
424                         Assert.AreEqual (42.0f, typeof (BinderTest).GetMethod ("FloatMethod").Invoke (null, new object[] { (char)42 }));
425                 }
426
427                 [Test]
428                 public void TestExactBinding ()
429                 {
430                         Type[] types = new Type[] { typeof(int) };
431                         Assert.AreEqual (null, typeof (BinderTest).GetMethod("MethodWithLongParam", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.ExactBinding,  null, types, null));
432                 }
433
434                 public void Bug42457Method (object thing)
435                 {
436                         bug42457 = 1;
437                 }
438
439                 public void Bug42457Method (Array thing)
440                 {
441                         bug42457 = 2;
442                 }
443
444                 public void Bug42457Method (string [] thing)
445                 {
446                         bug42457 = 3;
447                 }
448
449                 public void Bug42457Method2 (object thing)
450                 {
451                         bug42457_2 = 1;
452                 }
453
454                 public void Bug42457Method2 (Array thing)
455                 {
456                         bug42457_2 = 2;
457                 }
458
459                 public void Bug42457Method2 (string [] thing)
460                 {
461                         bug42457_2 = 3;
462                 }
463
464                 int bug42457, bug42457_2;
465
466                 [Test] // bug #77079
467                 public void GetMethodAvoidAmbiguity2 ()
468                 {
469                         Type tType = this.GetType ();
470                         Bug77079A a = new Bug77079C ();
471
472                         tType.InvokeMember ("Bug77079",
473                                 BindingFlags.Public | BindingFlags.InvokeMethod | 
474                                 BindingFlags.Instance,
475                                 null, this, new object[] {a});
476                         Assert.AreEqual (2, bug77079);
477                 }
478
479                 int bug77079;
480
481                 public void Bug77079 (Bug77079A a)
482                 {
483                         bug77079 = 1;
484                 }
485
486                 public void Bug77079 (Bug77079B a)
487                 {
488                         bug77079 = 2;
489                 }
490
491                 public class Bug77079A
492                 {
493                 }
494
495                 public class Bug77079B : Bug77079A
496                 {
497                 }
498
499                 public class Bug77079C : Bug77079B
500                 {
501                 }
502
503                 [Test] // bug #76083
504                 public void GetMethodAvoidAmbiguity3 ()
505                 {
506                         Type[] types = new Type[] { typeof (Bug76083ArgDerived) };
507                         MethodInfo m = typeof (Bug76083Derived).GetMethod ("Foo", types);
508                         Assert.AreEqual (typeof (Bug76083Derived), m.DeclaringType);
509                 }
510
511                 public class Bug76083ArgBase {}
512                 public class Bug76083ArgDerived : Bug76083ArgBase {}
513
514                 public class Bug76083Base
515                 {
516                         public void Foo (Bug76083ArgBase a) {}
517                 }
518
519                 public class Bug76083Derived : Bug76083Base
520                 {
521                         public new void Foo (Bug76083ArgBase a) {}
522                 }
523
524                 private const BindingFlags BUG324998_BINDING_FLAGS
525                         = BindingFlags.Public | BindingFlags.NonPublic
526                         | BindingFlags.Instance | BindingFlags.Static
527                         | BindingFlags.IgnoreCase;
528
529                 class Bug324998AGood { public virtual void f(int i1, int i2, bool b) {} }
530
531                 class Bug324998BGood : Bug324998AGood { public override void f(int i1, int i2, bool b) {} }
532
533                 class Bug324998ABad {
534                         public virtual void f(int i1, int i2) {}
535                         public virtual void f(int i1, int i2, bool b) {}
536                 }
537
538                 class Bug324998BBad : Bug324998ABad { public override void f(int i1, int i2, bool b) {} }
539
540                 [Test]
541                 public void Bug324998Good () {
542                         if (typeof(Bug324998BGood).GetMethod("f", BUG324998_BINDING_FLAGS) == null)
543                                 throw new Exception("Bug324998Good");
544                 }
545
546                 [Test]
547                 [ExpectedException (typeof (AmbiguousMatchException))]
548                 public void Bug324998Bad () {
549                         typeof(Bug324998BBad).GetMethod("f", BUG324998_BINDING_FLAGS);
550                 }
551
552         void Bug380361 (MyEnum e) { }
553
554         [Test]
555         public void TestEnumConversion ()
556         {
557             Type type = this.GetType ();
558             MethodInfo mi = type.GetMethod ("Bug380361", BindingFlags.NonPublic | BindingFlags.Instance, binder, new Type [] { typeof (MyEnum) }, null);
559             mi.Invoke (this, new object [] { (int)MyEnum.Zero });
560         }
561
562         [Test]
563         [ExpectedException(typeof (ArgumentException))]
564         public void TestEnumConversion2 ()
565         {
566             Type type = this.GetType ();
567             MethodInfo mi = type.GetMethod ("Bug380361", BindingFlags.NonPublic | BindingFlags.Instance, binder, new Type [] { typeof (MyEnum) }, null);
568             mi.Invoke (this, new object [] { (long)MyEnum.Zero });
569         }
570
571                 class AssertingBinder : Binder {
572
573                         public static readonly AssertingBinder Instance = new AssertingBinder ();
574
575                         public override FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo [] match, object value, CultureInfo culture)
576                         {
577                                 Assert.IsNotNull (match);
578
579                                 return Type.DefaultBinder.BindToField (bindingAttr, match, value, culture);
580                         }
581
582                         public override MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase [] match, ref object [] args, ParameterModifier [] modifiers, CultureInfo culture, string [] names, out object state)
583                         {
584                                 Assert.IsNotNull (match);
585                                 Assert.IsNotNull (args);
586
587                                 return Type.DefaultBinder.BindToMethod (bindingAttr, match, ref args, modifiers, culture, names, out state);
588                         }
589
590                         public override object ChangeType (object value, Type type, CultureInfo culture)
591                         {
592                                 Assert.IsNotNull (value);
593                                 Assert.IsNotNull (type);
594
595                                 return Type.DefaultBinder.ChangeType (value, type, culture);
596                         }
597
598                         public override void ReorderArgumentArray (ref object [] args, object state)
599                         {
600                                 Assert.IsNotNull (args);
601
602                                 Type.DefaultBinder.ReorderArgumentArray (ref args, state);
603                         }
604
605                         public override MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase [] match, Type [] types, ParameterModifier [] modifiers)
606                         {
607                                 Assert.IsNotNull (match);
608                                 Assert.IsNotNull (types);
609
610                                 return Type.DefaultBinder.SelectMethod (bindingAttr, match, types, modifiers);
611                         }
612
613                         public override PropertyInfo SelectProperty (BindingFlags bindingAttr, PropertyInfo [] match, Type returnType, Type [] indexes, ParameterModifier [] modifiers)
614                         {
615                                 Assert.IsNotNull (match);
616
617                                 return Type.DefaultBinder.SelectProperty (bindingAttr, match, returnType, indexes, modifiers);
618                         }
619                 }
620
621                 class BaseFoo {
622                         public void Bar ()
623                         {
624                         }
625
626                         public int Add(int x, int y)
627                         {
628                                 return x + y;   
629                         }
630                 }
631
632                 class Foo : BaseFoo {
633
634                         public bool Barred;
635
636                         public new void Bar ()
637                         {
638                                 Barred = true;
639                         }
640                 }
641
642                 class ByRefMatch {
643                         public void Run (int i)
644                         {
645                         }
646
647                         public void Run (out int i)
648                         {
649                                 i = 0;
650                         }
651                 }
652
653                 [Test] // bug  #471257
654                 public void TestCustomBinderNonNullArgs ()
655                 {
656                         var foo = new Foo ();
657
658                         typeof (Foo).InvokeMember (
659                                 "Bar",
660                                 BindingFlags.InvokeMethod,
661                                 AssertingBinder.Instance,
662                                 foo,
663                                 null);
664
665                         Assert.IsTrue (foo.Barred);
666                 }
667
668                 class Int32Binder : AssertingBinder
669                 {
670                         public override object ChangeType(Object value, Type type, CultureInfo ci)
671                         {
672                                 if (value.GetType() == type) {
673                                         return value;
674                                 } else if (type.IsPrimitive) {
675                                         if (type == typeof(Int32))
676                                                 return Convert.ToInt32(value);
677
678                                         throw new ArgumentException("missing support for primitive: " + type);
679                                 }
680
681                                 throw new ArgumentException("Could not ChangeType to " + type.FullName);
682                         }
683                 }
684
685                 [Test]
686                 [ExpectedException(typeof (TargetParameterCountException))]
687                 public void TestTargetParameterCountExceptionA ()
688                 {
689                         MethodInfo method = typeof (Foo).GetMethod ("Add");
690                         method.Invoke((new Foo ()), 0, null, null, null);
691                 }
692
693                 [Test]
694                 [ExpectedException(typeof (TargetParameterCountException))]
695                 public void TestTargetParameterCountExceptionB ()
696                 {
697                         MethodInfo method = typeof (Foo).GetMethod ("Add");
698                         method.Invoke(new Foo (), 0, null, new object [] {1}, null);
699                 }
700
701                 [Test]
702                 public void TestBindingFlagsA ()
703                 {
704                         MethodInfo method = typeof (Foo).GetMethod ("Add");
705                         method.Invoke((new Foo ()), 0, null, new object [] {1, 2}, null);
706                 }
707
708                 [Test]
709                 [ExpectedException(typeof (ArgumentException))]
710                 public void TestBindingFlagsB ()
711                 {
712                         MethodInfo method = typeof (Foo).GetMethod ("Add");
713                         method.Invoke((new Foo ()), 0, null, new object [] {1, "2"}, null);
714                 }
715
716                 [Test]
717                 public void TestBindingFlagsExactBindingA ()
718                 {
719                         MethodInfo method = typeof (Foo).GetMethod ("Add");
720                         method.Invoke((new Foo ()), BindingFlags.ExactBinding, null, new object [] {1, 2}, null);
721                 }
722
723                 [Test]
724                 [ExpectedException(typeof (ArgumentException))]
725                 public void TestBindingFlagsExactBindingB ()
726                 {
727                         MethodInfo method = typeof (Foo).GetMethod ("Add");
728                         method.Invoke((new Foo ()), BindingFlags.ExactBinding, new Int32Binder (), new object [] {1, "2"}, null);
729                 }
730
731                 [Test]
732                 public void TestBindingFlagsExactBindingC ()
733                 {
734                         MethodInfo method = typeof (Foo).GetMethod ("Add");
735                         method.Invoke((new Foo ()), 0, new Int32Binder (), new object [] {1, "2"}, null);
736                 }
737         }
738 }