2009-08-26 Sebastien Pouliot <sebastien@ximian.com>
[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                 [Category ("NotWorking")]
209                 public void SelectMethod_AmbiguousMatch ()
210                 {
211                         Type type = typeof (BinderTest);
212                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
213                         MethodBase [] match;
214                         Type [] types;
215
216                         types = new Type [] { typeof (object), typeof (object []) };
217                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
218                         Assert.IsNotNull (mi_params, "#A1");
219                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#A2");
220                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
221                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
222                         types = new Type [] { typeof (object) };
223                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
224                         Assert.IsNotNull (mi_single_param, "#B1");
225                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#B2");
226                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#B3");
227
228                         match = new MethodBase [] { mi_single_param, mi_single_param };
229                         types = new Type [] { typeof (object) };
230                         try {
231                                 binder.SelectMethod (flags, match, types, null);
232                                 Assert.Fail ("#C1");
233                         } catch (AmbiguousMatchException) {
234                                 // Ambiguous match found
235                         }
236
237                         match = new MethodBase [] { mi_single_param, mi_single_param };
238                         types = new Type [] { typeof (string) };
239                         try {
240                                 binder.SelectMethod (flags, match, types, null);
241                                 Assert.Fail ("#D1");
242                         } catch (AmbiguousMatchException) {
243                                 // Ambiguous match found
244                         }
245                 }
246
247                 [Test]
248                 public void SelectMethod_ByRef ()
249                 {
250                         Type type = typeof (ByRefMatch);
251                         BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance;
252                         MethodBase [] match;
253                         Type [] types;
254                         MethodBase selected;
255                         Type ref_int;
256
257                         MethodInfo mi_run = type.GetMethod ("Run", flags, binder,
258                                 new Type [] { typeof (int) }, null);
259                         Assert.IsFalse (mi_run.GetParameters () [0].ParameterType.IsByRef, "#A1");
260 #if NET_2_0
261                         MethodInfo mi_run_ref = type.GetMethod ("Run", flags, binder,
262                                 new Type [] { typeof (int).MakeByRefType () }, null);
263 #else
264                         MethodInfo mi_run_ref = type.GetMethod ("RunV1", flags);
265 #endif
266                         Assert.IsTrue (mi_run_ref.GetParameters () [0].ParameterType.IsByRef, "#A2");
267
268 #if NET_2_0
269                         ref_int = typeof (int).MakeByRefType ();
270 #else
271                         ref_int = mi_run_ref.GetParameters () [0].ParameterType;
272 #endif
273
274                         match = new MethodBase [] { mi_run_ref };
275                         types = new Type [] { typeof (int) };
276                         selected = binder.SelectMethod (flags, match, types, null);
277                         Assert.IsNull (selected, "#B1");
278                         types = new Type [] { ref_int };
279                         selected = binder.SelectMethod (flags, match, types, null);
280                         Assert.AreSame (mi_run_ref, selected, "#B2");
281
282                         match = new MethodBase [] { mi_run };
283                         types = new Type [] { typeof (int) };
284                         selected = binder.SelectMethod (flags, match, types, null);
285                         Assert.AreSame (mi_run, selected, "#C1");
286                         types = new Type [] { ref_int };
287                         selected = binder.SelectMethod (flags, match, types, null);
288                         Assert.IsNull (selected, "#C1");
289
290                         match = new MethodBase [] { mi_run, mi_run_ref };
291                         types = new Type [] { typeof (int) };
292                         selected = binder.SelectMethod (flags, match, types, null);
293                         Assert.AreSame (mi_run, selected, "#D1");
294                         types = new Type [] { ref_int };
295                         selected = binder.SelectMethod (flags, match, types, null);
296                         Assert.AreSame (mi_run_ref, selected, "#D2");
297                 }
298
299                 [Test]
300                 [Category ("NotWorking")]
301                 public void SelectMethod_Params ()
302                 {
303                         Type type = typeof (BinderTest);
304                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
305                         MethodBase [] match;
306                         Type [] types;
307                         MethodBase selected;
308
309                         types = new Type [] { typeof (object), typeof (object) };
310                         MethodInfo mi_non_params = type.GetMethod ("params_method1", flags, binder, types, null);
311                         Assert.IsNotNull (mi_non_params, "#A1");
312                         Assert.AreEqual (2, mi_non_params.GetParameters ().Length, "#A2");
313                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [0].ParameterType, "#A3");
314                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [1].ParameterType, "#A4");
315                         types = new Type [] { typeof (object), typeof (object []) };
316                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
317                         Assert.IsNotNull (mi_params, "#B1");
318                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#B2");
319                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
320                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
321                         types = new Type [] { typeof (object) };
322                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
323                         Assert.IsNotNull (mi_single_param, "#C1");
324                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#C2");
325                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#C3");
326
327                         match = new MethodBase [] { mi_params };
328                         types = new Type [] { typeof (object) };
329                         selected = binder.SelectMethod (flags, match, types, null);
330                         Assert.IsNull (selected, "#D1");
331                         types = new Type [] { typeof (object), typeof (object) };
332                         selected = binder.SelectMethod (flags, match, types, null);
333                         Assert.IsNull (selected, "#D2");
334                         types = new Type [] { typeof (object), typeof (object []) };
335                         selected = binder.SelectMethod (flags, match, types, null);
336                         Assert.AreSame (mi_params, selected, "#D3");
337                         types = new Type [] { typeof (object), typeof (object), typeof (object) };
338                         selected = binder.SelectMethod (flags, match, types, null);
339                         Assert.IsNull (selected, "#D4");
340
341                         match = new MethodBase [] { mi_non_params };    
342                         types = new Type [] { typeof (object) };
343                         selected = binder.SelectMethod (flags, match, types, null);
344                         Assert.IsNull (selected, "#E1");
345                         types = new Type [] { typeof (object), typeof (object) };
346                         selected = binder.SelectMethod (flags, match, types, null);
347                         Assert.AreSame (mi_non_params, selected, "#E2");
348                         types = new Type [] { typeof (object), typeof (object []) };
349                         selected = binder.SelectMethod (flags, match, types, null);
350                         Assert.AreSame (mi_non_params, selected, "#E3");
351                         types = new Type [] { typeof (object), typeof (object), typeof (object) };
352                         selected = binder.SelectMethod (flags, match, types, null);
353                         Assert.IsNull (selected, "#E4");
354
355                         match = new MethodBase [] { mi_non_params, mi_params };
356                         types = new Type [] { typeof (object) };
357                         selected = binder.SelectMethod (flags, match, types, null);
358                         Assert.IsNull (selected, "#F1");
359                         match = new MethodBase [] { mi_non_params, mi_params };
360                         types = new Type [] { typeof (object), typeof (object) };
361                         selected = binder.SelectMethod (flags, match, types, null);
362                         Assert.AreSame (mi_non_params, selected, "#F2");
363                         match = new MethodBase [] { mi_non_params, mi_params };
364                         types = new Type [] { typeof (object), typeof (object []) };
365                         selected = binder.SelectMethod (flags, match, types, null);
366                         Assert.AreSame (mi_params, selected, "#F3");
367                         match = new MethodBase [] { mi_non_params, mi_params };
368                         types = new Type [] { typeof (object), typeof (object), typeof (object) };
369                         selected = binder.SelectMethod (flags, match, types, null);
370                         Assert.IsNull (selected, "#F4");
371
372                         match = new MethodBase [] { mi_params, mi_non_params };
373                         types = new Type [] { typeof (object) };
374                         selected = binder.SelectMethod (flags, match, types, null);
375                         Assert.IsNull (selected, "#G1");
376                         match = new MethodBase [] { mi_params, mi_non_params };
377                         types = new Type [] { typeof (object), typeof (object) };
378                         selected = binder.SelectMethod (flags, match, types, null);
379                         Assert.AreSame (mi_non_params, selected, "#G2");
380                         match = new MethodBase [] { mi_params, mi_non_params };
381                         types = new Type [] { typeof (object), typeof (object []) };
382                         selected = binder.SelectMethod (flags, match, types, null);
383                         Assert.AreSame (mi_params, selected, "#G3");
384                         match = new MethodBase [] { mi_params, mi_non_params };
385                         types = new Type [] { typeof (object), typeof (object), typeof (object) };
386                         selected = binder.SelectMethod (flags, match, types, null);
387                         Assert.IsNull (selected, "#G4");
388
389                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
390                         types = new Type [] { typeof (object) };
391                         selected = binder.SelectMethod (flags, match, types, null);
392                         Assert.AreSame (mi_single_param, selected, "#H1");
393                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
394                         types = new Type [] { typeof (object), typeof (object) };
395                         selected = binder.SelectMethod (flags, match, types, null);
396                         Assert.AreSame (mi_non_params, selected, "#H2");
397                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
398                         types = new Type [] { typeof (object), typeof (object []) };
399                         selected = binder.SelectMethod (flags, match, types, null);
400                         Assert.AreSame (mi_params, selected, "#H3");
401                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
402                         types = new Type [] { typeof (object), typeof (object), typeof (object) };
403                         selected = binder.SelectMethod (flags, match, types, null);
404                         Assert.IsNull (selected, "#H4");
405
406                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
407                         types = new Type [] { typeof (string) };
408                         selected = binder.SelectMethod (flags, match, types, null);
409                         Assert.AreSame (mi_single_param, selected, "#I1");
410                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
411                         types = new Type [] { typeof (string), typeof (string) };
412                         selected = binder.SelectMethod (flags, match, types, null); 
413                         Assert.AreSame (mi_non_params, selected, "#I2");
414                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
415                         types = new Type [] { typeof (string), typeof (string []) };
416                         selected = binder.SelectMethod (flags, match, types, null);
417                         Assert.AreSame (mi_params, selected, "#I3");
418                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
419                         types = new Type [] { typeof (string), typeof (string), typeof (long) };
420                         selected = binder.SelectMethod (flags, match, types, null);
421                         Assert.IsNull (selected, "#I4");
422                 }
423
424                 [Test] // bug #314809
425                 public void ArgNullOnMethod ()
426                 {
427                         Type type = typeof (SampleClass);
428                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod;
429                         type.InvokeMember ("SampleMethod", flags, null, null, new object[] { null });
430                 }
431
432                 [Test]
433                 public void ArgNullOnProperty ()
434                 {
435                         Type type = typeof (SampleClass);
436                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
437                                                                     BindingFlags.Public |
438                                                                     BindingFlags.Instance);
439
440                         PropertyInfo prop = binder.SelectProperty (0, props, null, new Type [] {null}, null);
441                         Assert.IsNotNull (prop);
442                 }
443
444                 [Test]
445                 public void BindToMethod_ByRef ()
446                 {
447                         Type type = typeof (ByRefMatch);
448                         BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance;
449                         MethodBase [] match;
450                         object [] args = new object [] { 5 };
451                         object state;
452                         MethodBase selected;
453                         CultureInfo culture = CultureInfo.InvariantCulture;
454
455                         MethodInfo mi_run = type.GetMethod ("Run", flags, binder,
456                                 new Type [] { typeof (int) }, null);
457                         Assert.IsFalse (mi_run.GetParameters () [0].ParameterType.IsByRef, "#A1");
458 #if NET_2_0
459                         MethodInfo mi_run_ref = type.GetMethod ("Run", flags, binder,
460                                 new Type [] { typeof (int).MakeByRefType () }, null);
461 #else
462                         MethodInfo mi_run_ref = type.GetMethod ("RunV1", flags);
463 #endif
464                         Assert.IsTrue (mi_run_ref.GetParameters () [0].ParameterType.IsByRef, "#A2");
465
466                         match = new MethodBase [] { mi_run };
467                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
468                                 null, out state);
469                         Assert.AreSame (mi_run, selected, "#B1");
470
471                         match = new MethodBase [] { mi_run_ref };
472                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
473                                 null, out state);
474                         Assert.AreSame (mi_run_ref, selected, "#B2");
475
476                         match = new MethodBase [] { mi_run, mi_run_ref };
477                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
478                                 null, out state);
479                         Assert.AreSame (mi_run, selected, "#B3");
480
481                         match = new MethodBase [] { mi_run_ref, mi_run };
482                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
483                                 null, out state);
484                         Assert.AreSame (mi_run, selected, "#B4");
485                 }
486
487                 [Test]
488                 [Category ("NotWorking")]
489                 public void BindToMethod_AmbiguousMatch ()
490                 {
491                         Type type = typeof (BinderTest);
492                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
493                         MethodBase [] match;
494                         Type [] types;
495                         object state;
496                         object [] args;
497                         CultureInfo culture = CultureInfo.InvariantCulture;
498
499                         types = new Type [] { typeof (object), typeof (object []) };
500                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
501                         Assert.IsNotNull (mi_params, "#A1");
502                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#A2");
503                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
504                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
505                         types = new Type [] { typeof (object) };
506                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
507                         Assert.IsNotNull (mi_single_param, "#B1");
508                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#B2");
509                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#B3");
510
511                         match = new MethodBase [] { mi_single_param, mi_single_param };
512                         args = new object [] { new object () };
513                         try {
514                                 binder.BindToMethod (flags, match, ref args, null, culture,
515                                         null, out state);
516                                 Assert.Fail ("#C1");
517                         } catch (AmbiguousMatchException) {
518                                 // Ambiguous match found
519                         }
520
521                         match = new MethodBase [] { mi_single_param, mi_single_param };
522                         args = new object [] { string.Empty };
523                         try {
524                                 binder.BindToMethod (flags, match, ref args, null, culture,
525                                         null, out state);
526                                 Assert.Fail ("#D1");
527                         } catch (AmbiguousMatchException) {
528                                 // Ambiguous match found
529                         }
530
531                         match = new MethodBase [] { mi_params, mi_params };
532                         args = new object [] { new object (), new object () };
533                         try {
534                                 binder.BindToMethod (flags, match, ref args, null, culture,
535                                         null, out state);
536                                 Assert.Fail ("#E1");
537                         } catch (AmbiguousMatchException) {
538                                 // Ambiguous match found
539                         }
540
541                         match = new MethodBase [] { mi_params, mi_params };
542                         args = new object [] { string.Empty, 0L };
543                         try {
544                                 binder.BindToMethod (flags, match, ref args, null, culture,
545                                         null, out state);
546                                 Assert.Fail ("#F1");
547                         } catch (AmbiguousMatchException) {
548                                 // Ambiguous match found
549                         }
550                 }
551
552                 [Test]
553                 [Category ("NotWorking")]
554                 public void BindToMethod_Params ()
555                 {
556                         Type type = typeof (BinderTest);
557                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
558                         MethodBase [] match;
559                         Type [] types;
560                         MethodBase selected;
561                         object state;
562                         object [] args;
563                         CultureInfo culture = CultureInfo.InvariantCulture;
564
565                         types = new Type [] { typeof (object), typeof (object) };
566                         MethodInfo mi_non_params = type.GetMethod ("params_method1", flags, binder, types, null);
567                         Assert.IsNotNull (mi_non_params, "#A1");
568                         Assert.AreEqual (2, mi_non_params.GetParameters ().Length, "#A2");
569                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [0].ParameterType, "#A3");
570                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [1].ParameterType, "#A4");
571                         types = new Type [] { typeof (object), typeof (object []) };
572                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
573                         Assert.IsNotNull (mi_params, "#B1");
574                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#B2");
575                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
576                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
577                         types = new Type [] { typeof (object) };
578                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
579                         Assert.IsNotNull (mi_single_param, "#C1");
580                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#C2");
581                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#C3");
582
583                         match = new MethodBase [] { mi_params };
584                         args = new object [] { new object () };
585                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
586                                 null, out state);
587                         Assert.AreSame (mi_params, selected, "#D1");
588                         args = new object [] { new object (), new object () };
589                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
590                                 null, out state);
591                         Assert.AreSame (mi_params, selected, "#D2");
592                         args = new object [] { new object (), new object [0] };
593                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
594                                 null, out state);
595                         Assert.AreSame (mi_params, selected, "#D3");
596                         args = new object [] { new object (), new object (), new object () };
597                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
598                                 null, out state);
599                         Assert.AreSame (mi_params, selected, "#D4");
600
601                         match = new MethodBase [] { mi_non_params };
602                         args = new object [] { new object () };
603                         try {
604                                 binder.BindToMethod (flags, match, ref args, null, culture,
605                                         null, out state);
606                                 Assert.Fail ("#E1");
607                         } catch (MissingMethodException) {
608                                 // Member not found
609                         }
610                         args = new object [] { new object (), new object () };
611                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
612                                 null, out state);
613                         Assert.AreSame (mi_non_params, selected, "#E2");
614                         args = new object [] { new object (), new object [0] };
615                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
616                                 null, out state);
617                         Assert.AreSame (mi_non_params, selected, "#E3");
618                         args = new object [] { new object (), new object (), new object () };
619                         try {
620                                 binder.BindToMethod (flags, match, ref args, null, culture,
621                                         null, out state);
622                                 Assert.Fail ("#E4");
623                         } catch (MissingMethodException) {
624                                 // Member not found
625                         }
626
627                         match = new MethodBase [] { mi_non_params, mi_params };
628                         args = new object [] { new object () };
629                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
630                                 null, out state);
631                         Assert.AreSame (mi_params, selected, "#F1");
632                         match = new MethodBase [] { mi_non_params, mi_params };
633                         args = new object [] { new object (), new object () };
634                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
635                                 null, out state);
636                         Assert.AreSame (mi_non_params, selected, "#F2");
637                         match = new MethodBase [] { mi_non_params, mi_params };
638                         args = new object [] { new object (), new object [0] };
639                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
640                                 null, out state);
641                         Assert.AreSame (mi_params, selected, "#F3");
642                         match = new MethodBase [] { mi_non_params, mi_params };
643                         args = new object [] { new object (), new object (), new object () };
644                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
645                                 null, out state);
646                         Assert.AreSame (mi_params, selected, "#F4");
647
648                         match = new MethodBase [] { mi_params, mi_non_params };
649                         args = new object [] { new object () };
650                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
651                                 null, out state);
652                         Assert.AreSame (mi_params, selected, "#G1");
653                         match = new MethodBase [] { mi_params, mi_non_params };
654                         args = new object [] { new object (), new object () };
655                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
656                                 null, out state);
657                         Assert.AreSame (mi_non_params, selected, "#G2");
658                         match = new MethodBase [] { mi_params, mi_non_params };
659                         args = new object [] { new object (), new object [0] };
660                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
661                                 null, out state);
662                         Assert.AreSame (mi_params, selected, "#G3");
663                         match = new MethodBase [] { mi_params, mi_non_params };
664                         args = new object [] { new object (), new object (), new object () };
665                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
666                                 null, out state);
667                         Assert.AreSame (mi_params, selected, "#G4");
668
669                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
670                         args = new object [] { new object () };
671                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
672                                 null, out state);
673                         Assert.AreSame (mi_single_param, selected, "#H1");
674                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
675                         args = new object [] { new object (), new object () };
676                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
677                                 null, out state);
678                         Assert.AreSame (mi_non_params, selected, "#H2");
679                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
680                         args = new object [] { new object (), new object [0] };
681                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
682                                 null, out state);
683                         Assert.AreSame (mi_params, selected, "#H3");
684                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
685                         args = new object [] { new object (), new object (), new object () };
686                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
687                                 null, out state);
688                         Assert.AreSame (mi_params, selected, "#H4");
689
690                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
691                         args = new object [] { string.Empty };
692                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
693                                 null, out state);
694                         Assert.AreSame (mi_single_param, selected, "#I1");
695                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
696                         args = new object [] { string.Empty, string.Empty };
697                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
698                                 null, out state);
699                         Assert.AreSame (mi_non_params, selected, "#I2");
700                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
701                         args = new object [] { string.Empty, new string [0] };
702                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
703                                 null, out state);
704                         Assert.AreSame (mi_params, selected, "#I3");
705                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
706                         args = new object [] { string.Empty, string.Empty, 5L };
707                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
708                                 null, out state);
709                         Assert.AreSame (mi_params, selected, "#I4");
710                 }
711
712                 [Test]
713                 [Category ("NotDotNet")]
714                 [Category ("NotWorking")]
715                 public void BindToMethod_Params_Mono ()
716                 {
717                         Type type = typeof (BinderTest);
718                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
719                         MethodBase [] match;
720                         Type [] types;
721                         MethodBase selected;
722                         object state;
723                         object [] args;
724                         CultureInfo culture = CultureInfo.InvariantCulture;
725
726                         types = new Type [] { typeof (object), typeof (object) };
727                         MethodInfo mi_non_params = type.GetMethod ("params_method1", flags, binder, types, null);
728                         Assert.IsNotNull (mi_non_params, "#A1");
729                         Assert.AreEqual (2, mi_non_params.GetParameters ().Length, "#A2");
730                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [0].ParameterType, "#A3");
731                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [1].ParameterType, "#A4");
732                         types = new Type [] { typeof (object), typeof (object []) };
733                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
734                         Assert.IsNotNull (mi_params, "#B1");
735                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#B2");
736                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
737                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
738                         types = new Type [] { typeof (object) };
739                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
740                         Assert.IsNotNull (mi_single_param, "#C1");
741                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#C2");
742                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#C3");
743
744                         match = new MethodBase [] { mi_non_params, mi_params };
745                         args = new object [] { new object () };
746                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
747                                 null, out state);
748                         Assert.AreSame (mi_params, selected, "#D1");
749                         args = new object [] { new object (), new object () };
750                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
751                                 null, out state);
752                         Assert.AreSame (mi_non_params, selected, "#D2");
753                         args = new object [] { new object (), new object [0] };
754                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
755                                 null, out state);
756                         Assert.AreSame (mi_params, selected, "#D3");
757                         args = new object [] { new object (), new object (), new object () };
758                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
759                                 null, out state);
760                         Assert.AreSame (mi_params, selected, "#D4");
761
762                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
763                         args = new object [] { new object () };
764                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
765                                 null, out state);
766                         Assert.AreSame (mi_single_param, selected, "#E1");
767                         args = new object [] { new object (), new object () };
768                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
769                                 null, out state);
770                         Assert.AreSame (mi_non_params, selected, "#E2");
771                 }
772
773                 [Test]
774                 [Category ("NotWorking")]
775                 public void BindToMethod_Params_MS ()
776                 {
777                         Type type = typeof (BinderTest);
778                         BindingFlags flags = BindingFlags.Static | BindingFlags.Public;
779                         MethodBase [] match;
780                         Type [] types;
781                         MethodBase selected;
782                         object state;
783                         object [] args;
784                         CultureInfo culture = CultureInfo.InvariantCulture;
785
786                         types = new Type [] { typeof (object), typeof (object) };
787                         MethodInfo mi_non_params = type.GetMethod ("params_method1", flags, binder, types, null);
788                         Assert.IsNotNull (mi_non_params, "#A1");
789                         Assert.AreEqual (2, mi_non_params.GetParameters ().Length, "#A2");
790                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [0].ParameterType, "#A3");
791                         Assert.AreEqual (typeof (object), mi_non_params.GetParameters () [1].ParameterType, "#A4");
792                         types = new Type [] { typeof (object), typeof (object []) };
793                         MethodInfo mi_params = type.GetMethod ("params_method1", flags, binder, types, null);
794                         Assert.IsNotNull (mi_params, "#B1");
795                         Assert.AreEqual (2, mi_params.GetParameters ().Length, "#B2");
796                         Assert.AreEqual (typeof (object), mi_params.GetParameters () [0].ParameterType, "#B3");
797                         Assert.AreEqual (typeof (object []), mi_params.GetParameters () [1].ParameterType, "#B4");
798                         types = new Type [] { typeof (object) };
799                         MethodInfo mi_single_param = type.GetMethod ("params_method1", flags, binder, types, null);
800                         Assert.IsNotNull (mi_single_param, "#C1");
801                         Assert.AreEqual (1, mi_single_param.GetParameters ().Length, "#C2");
802                         Assert.AreEqual (typeof (object), mi_single_param.GetParameters () [0].ParameterType, "#C3");
803
804                         match = new MethodBase [] { mi_non_params, mi_params };
805                         args = new object [] { new object () };
806                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
807                                 null, out state);
808                         Assert.AreSame (mi_params, selected, "#D1");
809                         args = new object [] { new object (), new object () };
810                         try {
811                                 binder.BindToMethod (flags, match, ref args, null, culture,
812                                         null, out state);
813                                 Assert.Fail ("#D2");
814                         } catch (AmbiguousMatchException) {
815                         }
816                         args = new object [] { new object (), new object [0] };
817                         try {
818                                 binder.BindToMethod (flags, match, ref args, null, culture,
819                                         null, out state);
820                                 Assert.Fail ("#D3");
821                         } catch (AmbiguousMatchException) {
822                         }
823                         args = new object [] { new object (), new object (), new object () };
824                         try {
825                                 binder.BindToMethod (flags, match, ref args, null, culture,
826                                         null, out state);
827                                 Assert.Fail ("#D4");
828                         } catch (IndexOutOfRangeException) {
829                         }
830
831                         match = new MethodBase [] { mi_params, mi_non_params, mi_single_param };
832                         args = new object [] { new object () };
833                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
834                                 null, out state);
835                         Assert.AreSame (mi_single_param, selected, "#E1");
836                         args = new object [] { new object (), new object () };
837                         selected = binder.BindToMethod (flags, match, ref args, null, culture,
838                                 null, out state);
839                         Assert.AreSame (mi_params, selected, "#E2");
840                 }
841
842                 [Test] // bug #41691
843                 public void BindToMethodNamedArgs ()
844                 {
845                         Type t = typeof (Bug41691);
846
847                         StringWriter sw = new StringWriter ();
848                         sw.NewLine = "\n";
849
850                         object[] argValues = new object [] {"Hello", "World", "Extra", sw};
851                         string [] argNames = new string [] {"firstName", "lastName"};
852
853                         t.InvokeMember ("PrintName",
854                                         BindingFlags.InvokeMethod,
855                                         null,
856                                         null,
857                                         argValues,
858                                         null,
859                                         null,
860                                         argNames);
861
862                         Assert.AreEqual ("Hello\nExtra\nWorld\n", sw.ToString ());
863                 }
864
865                 public class Bug41691
866                 {
867                         public static void PrintName (string lastName, string firstName, string extra, TextWriter output)
868                         {
869                                 output.WriteLine (firstName);
870                                 output.WriteLine (extra);
871                                 output.WriteLine (lastName);
872                         }
873                 }
874
875                 [Test] // bug #42457
876                 public void GetMethodAmbiguity ()
877                 {
878                         object IntegerObject = 5;
879                         object IntArrayObject = new int[] {5, 2, 5};
880                         object StringArrayObject = new string [] {"One", "Two"};
881                         object [] IntParam = new object [] {IntegerObject};
882                         object [] IntArrayParam = new object [] {IntArrayObject};
883                         object [] StringArrayParam = new object [] {StringArrayObject};
884
885                         object be = this;
886                         Type betype = this.GetType ();
887
888                         string name1 = "Bug42457Method";
889                         string name2 = "Bug42457Method2";
890
891                         MethodInfo mi_obj = betype.GetMethod (name1, Type.GetTypeArray (IntParam));
892                         mi_obj.Invoke (be, IntParam);
893                         Assert.AreEqual (1, bug42457, "#1");
894                         MethodInfo mi_arr = betype.GetMethod (name1, Type.GetTypeArray (IntArrayParam));
895                         mi_arr.Invoke (be, IntArrayParam);
896                         Assert.AreEqual (2, bug42457, "#2");
897                         MethodInfo mi_str = betype.GetMethod (name1, Type.GetTypeArray (StringArrayParam));
898                         mi_str.Invoke (be, StringArrayParam);
899                         Assert.AreEqual (3, bug42457, "#3");
900
901                         MethodInfo m2_obj = betype.GetMethod (name2, Type.GetTypeArray (IntParam));
902                         m2_obj.Invoke (be, IntParam);
903                         Assert.AreEqual (1, bug42457_2, "#4");
904                         MethodInfo m2_arr = betype.GetMethod (name2, Type.GetTypeArray (IntArrayParam));
905                         m2_arr.Invoke (be, IntArrayParam);
906                         Assert.AreEqual (2, bug42457_2, "#5");
907                         MethodInfo m2_str = betype.GetMethod (name2, Type.GetTypeArray(StringArrayParam));
908                         m2_str.Invoke (be, StringArrayParam);
909                         Assert.AreEqual (3, bug42457_2, "#6");
910                 }
911
912 #if NET_2_0
913                 [Test]
914                 public void NullableArg () {
915                         MethodInfo method = (typeof (BinderTest)).GetMethod("SetA", new [] {typeof (Int32)});
916                         Assert.AreEqual (5, method.Invoke (new BinderTest (), new object [] { 5 }));
917                 }
918
919                 public int SetA(Int32? a) {
920                         return (int)a;
921                 }
922 #endif
923
924                 static void MethodWithLongParam(long param)
925                 {
926                 }
927
928                 [Test]
929                 public void TestParamsAttribute ()
930                 {
931                         MethodInfo mi;
932
933                         mi = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object), typeof (object) }, null);
934                         Assert.IsNotNull (mi, "#A1");
935                         Assert.AreEqual (typeof (object), mi.GetParameters () [1].ParameterType, "#A2");
936
937                         mi = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object), typeof (object []) }, null);
938                         Assert.IsNotNull (mi, "#B1");
939                         Assert.AreEqual (typeof (object []), mi.GetParameters () [1].ParameterType, "#B2");
940                 }
941
942                 [Test]
943                 [Category ("NotDotNet")]
944                 public void TestParamsAttribute2_Mono ()
945                 {
946                         MethodInfo mi = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static|BindingFlags.Public, null, new Type [] { typeof (object), typeof (object), typeof (object) }, null);
947                         Assert.IsNotNull (mi, "#1");
948                         Assert.AreEqual (typeof (object []), mi.GetParameters () [1].ParameterType, "#2");
949                 }
950
951                 [Test]
952                 [Category ("NotWorking")]
953                 public void TestParamsAttribute2_MS ()
954                 {
955                         MethodInfo mi = typeof (BinderTest).GetMethod ("params_method1", BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object), typeof (object), typeof (object) }, null);
956                         Assert.IsNull (mi, "#1");
957                 }
958
959                 public static void params_method1 (object o)
960                 {
961                 }
962
963                 public static void params_method1 (object o, params object[] o2)
964                 {
965                 }
966
967                 public static void params_method1 (object o, object o2)
968                 {
969                 }
970
971                 public static double DoubleMethod (double d) {
972                         return d;
973                 }
974
975                 public static float FloatMethod (float f) {
976                         return f;
977                 }
978
979                 [Test]
980                 public void ChangeType ()
981                 {
982                         // Char -> Double
983                         Assert.AreEqual (42.0, typeof (BinderTest).GetMethod ("DoubleMethod").Invoke (null, new object[] { (char)42 }));
984
985                         // Char -> Float
986                         Assert.AreEqual (42.0f, typeof (BinderTest).GetMethod ("FloatMethod").Invoke (null, new object[] { (char)42 }));
987                 }
988
989                 [Test]
990                 public void TestExactBinding ()
991                 {
992                         Type[] types = new Type[] { typeof(int) };
993                         BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.ExactBinding;
994                         Assert.IsNull (typeof (BinderTest).GetMethod("MethodWithLongParam",
995                                 flags, null, types, null));
996                 }
997
998                 public void Bug42457Method (object thing)
999                 {
1000                         bug42457 = 1;
1001                 }
1002
1003                 public void Bug42457Method (Array thing)
1004                 {
1005                         bug42457 = 2;
1006                 }
1007
1008                 public void Bug42457Method (string [] thing)
1009                 {
1010                         bug42457 = 3;
1011                 }
1012
1013                 public void Bug42457Method2 (object thing)
1014                 {
1015                         bug42457_2 = 1;
1016                 }
1017
1018                 public void Bug42457Method2 (Array thing)
1019                 {
1020                         bug42457_2 = 2;
1021                 }
1022
1023                 public void Bug42457Method2 (string [] thing)
1024                 {
1025                         bug42457_2 = 3;
1026                 }
1027
1028                 int bug42457, bug42457_2;
1029
1030                 [Test] // bug #77079
1031                 public void GetMethodAvoidAmbiguity2 ()
1032                 {
1033                         Type tType = this.GetType ();
1034                         Bug77079A a = new Bug77079C ();
1035
1036                         tType.InvokeMember ("Bug77079",
1037                                 BindingFlags.Public | BindingFlags.InvokeMethod | 
1038                                 BindingFlags.Instance,
1039                                 null, this, new object[] {a});
1040                         Assert.AreEqual (2, bug77079);
1041                 }
1042
1043                 int bug77079;
1044
1045                 public void Bug77079 (Bug77079A a)
1046                 {
1047                         bug77079 = 1;
1048                 }
1049
1050                 public void Bug77079 (Bug77079B a)
1051                 {
1052                         bug77079 = 2;
1053                 }
1054
1055                 public class Bug77079A
1056                 {
1057                 }
1058
1059                 public class Bug77079B : Bug77079A
1060                 {
1061                 }
1062
1063                 public class Bug77079C : Bug77079B
1064                 {
1065                 }
1066
1067                 [Test] // bug #76083
1068                 public void GetMethodAvoidAmbiguity3 ()
1069                 {
1070                         Type[] types = new Type[] { typeof (Bug76083ArgDerived) };
1071                         MethodInfo m = typeof (Bug76083Derived).GetMethod ("Foo", types);
1072                         Assert.AreEqual (typeof (Bug76083Derived), m.DeclaringType);
1073                 }
1074
1075                 public class Bug76083ArgBase {}
1076                 public class Bug76083ArgDerived : Bug76083ArgBase {}
1077
1078                 public class Bug76083Base
1079                 {
1080                         public void Foo (Bug76083ArgBase a) {}
1081                 }
1082
1083                 public class Bug76083Derived : Bug76083Base
1084                 {
1085                         public new void Foo (Bug76083ArgBase a) {}
1086                 }
1087
1088                 private const BindingFlags BUG324998_BINDING_FLAGS
1089                         = BindingFlags.Public | BindingFlags.NonPublic
1090                         | BindingFlags.Instance | BindingFlags.Static
1091                         | BindingFlags.IgnoreCase;
1092
1093                 class Bug324998AGood { public virtual void f(int i1, int i2, bool b) {} }
1094
1095                 class Bug324998BGood : Bug324998AGood { public override void f(int i1, int i2, bool b) {} }
1096
1097                 class Bug324998ABad {
1098                         public virtual void f(int i1, int i2) {}
1099                         public virtual void f(int i1, int i2, bool b) {}
1100                 }
1101
1102                 class Bug324998BBad : Bug324998ABad { public override void f(int i1, int i2, bool b) {} }
1103
1104                 [Test]
1105                 public void Bug324998Good () {
1106                         if (typeof(Bug324998BGood).GetMethod("f", BUG324998_BINDING_FLAGS) == null)
1107                                 throw new Exception("Bug324998Good");
1108                 }
1109
1110                 [Test]
1111                 [ExpectedException (typeof (AmbiguousMatchException))]
1112                 public void Bug324998Bad () {
1113                         typeof(Bug324998BBad).GetMethod("f", BUG324998_BINDING_FLAGS);
1114                 }
1115
1116                 void Bug380361 (MyEnum e) { }
1117
1118                 [Test]
1119                 public void TestEnumConversion ()
1120                 {
1121                         Type type = this.GetType ();
1122                         MethodInfo mi = type.GetMethod ("Bug380361", BindingFlags.NonPublic | BindingFlags.Instance, binder, new Type [] { typeof (MyEnum) }, null);
1123                         mi.Invoke (this, new object [] { (int)MyEnum.Zero });
1124                 }
1125
1126                 [Test]
1127                 public void TestEnumConversion2 ()
1128                 {
1129                         Type type = this.GetType ();
1130                         MethodInfo mi = type.GetMethod ("Bug380361", BindingFlags.NonPublic | BindingFlags.Instance, binder, new Type [] { typeof (MyEnum) }, null);
1131                         try {
1132                                 mi.Invoke (this, new object [] { (long) MyEnum.Zero });
1133                                 Assert.Fail ("#1");
1134                         } catch (ArgumentException ex) {
1135                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
1136                                 Assert.IsNull (ex.InnerException, "#3");
1137                                 Assert.IsNotNull (ex.Message, "#4");
1138                                 Assert.IsNull (ex.ParamName, "#5");
1139                         }
1140                 }
1141
1142                 class AssertingBinder : Binder {
1143
1144                         public static readonly AssertingBinder Instance = new AssertingBinder ();
1145
1146                         public override FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo [] match, object value, CultureInfo culture)
1147                         {
1148                                 Assert.IsNotNull (match);
1149
1150                                 return Type.DefaultBinder.BindToField (bindingAttr, match, value, culture);
1151                         }
1152
1153                         public override MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase [] match, ref object [] args, ParameterModifier [] modifiers, CultureInfo culture, string [] names, out object state)
1154                         {
1155                                 Assert.IsNotNull (match);
1156                                 Assert.IsNotNull (args);
1157
1158                                 return Type.DefaultBinder.BindToMethod (bindingAttr, match, ref args, modifiers, culture, names, out state);
1159                         }
1160
1161                         public override object ChangeType (object value, Type type, CultureInfo culture)
1162                         {
1163                                 Assert.IsNotNull (value);
1164                                 Assert.IsNotNull (type);
1165
1166                                 return Type.DefaultBinder.ChangeType (value, type, culture);
1167                         }
1168
1169                         public override void ReorderArgumentArray (ref object [] args, object state)
1170                         {
1171                                 Assert.IsNotNull (args);
1172
1173                                 Type.DefaultBinder.ReorderArgumentArray (ref args, state);
1174                         }
1175
1176                         public override MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase [] match, Type [] types, ParameterModifier [] modifiers)
1177                         {
1178                                 Assert.IsNotNull (match);
1179                                 Assert.IsNotNull (types);
1180
1181                                 return Type.DefaultBinder.SelectMethod (bindingAttr, match, types, modifiers);
1182                         }
1183
1184                         public override PropertyInfo SelectProperty (BindingFlags bindingAttr, PropertyInfo [] match, Type returnType, Type [] indexes, ParameterModifier [] modifiers)
1185                         {
1186                                 Assert.IsNotNull (match);
1187
1188                                 return Type.DefaultBinder.SelectProperty (bindingAttr, match, returnType, indexes, modifiers);
1189                         }
1190                 }
1191
1192                 class BaseFoo {
1193                         public void Bar ()
1194                         {
1195                         }
1196
1197                         public int Add(int x, int y)
1198                         {
1199                                 return x + y;   
1200                         }
1201                 }
1202
1203                 class Foo : BaseFoo {
1204
1205                         public bool Barred;
1206
1207                         public new void Bar ()
1208                         {
1209                                 Barred = true;
1210                         }
1211                 }
1212
1213                 class ByRefMatch {
1214                         public void Run (int i)
1215                         {
1216                         }
1217
1218 #if NET_2_0
1219                         public void Run (out int i)
1220 #else
1221                         public void RunV1 (out int i)
1222 #endif
1223                         {
1224                                 i = 0;
1225                         }
1226                 }
1227
1228                 [Test] // bug  #471257
1229                 public void TestCustomBinderNonNullArgs ()
1230                 {
1231                         var foo = new Foo ();
1232
1233                         typeof (Foo).InvokeMember (
1234                                 "Bar",
1235                                 BindingFlags.InvokeMethod,
1236                                 AssertingBinder.Instance,
1237                                 foo,
1238                                 null);
1239
1240                         Assert.IsTrue (foo.Barred);
1241                 }
1242
1243                 class Int32Binder : AssertingBinder
1244                 {
1245                         public override object ChangeType(Object value, Type type, CultureInfo ci)
1246                         {
1247                                 if (value.GetType() == type) {
1248                                         return value;
1249                                 } else if (type.IsPrimitive) {
1250                                         if (type == typeof(Int32))
1251                                                 return Convert.ToInt32(value);
1252
1253                                         throw new ArgumentException("missing support for primitive: " + type);
1254                                 }
1255
1256                                 throw new ArgumentException("Could not ChangeType to " + type.FullName);
1257                         }
1258                 }
1259
1260                 [Test]
1261                 [ExpectedException(typeof (TargetParameterCountException))]
1262                 public void TestTargetParameterCountExceptionA ()
1263                 {
1264                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1265                         method.Invoke((new Foo ()), 0, null, null, null);
1266                 }
1267
1268                 [Test]
1269                 [ExpectedException(typeof (TargetParameterCountException))]
1270                 public void TestTargetParameterCountExceptionB ()
1271                 {
1272                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1273                         method.Invoke(new Foo (), 0, null, new object [] {1}, null);
1274                 }
1275
1276                 [Test]
1277                 public void TestBindingFlagsA ()
1278                 {
1279                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1280                         method.Invoke((new Foo ()), 0, null, new object [] {1, 2}, null);
1281                 }
1282
1283                 [Test]
1284                 [ExpectedException(typeof (ArgumentException))]
1285                 public void TestBindingFlagsB ()
1286                 {
1287                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1288                         method.Invoke((new Foo ()), 0, null, new object [] {1, "2"}, null);
1289                 }
1290
1291                 [Test]
1292                 public void TestBindingFlagsExactBindingA ()
1293                 {
1294                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1295                         method.Invoke((new Foo ()), BindingFlags.ExactBinding, null, new object [] {1, 2}, null);
1296                 }
1297
1298                 [Test]
1299                 [ExpectedException(typeof (ArgumentException))]
1300                 public void TestBindingFlagsExactBindingB ()
1301                 {
1302                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1303                         method.Invoke((new Foo ()), BindingFlags.ExactBinding, new Int32Binder (), new object [] {1, "2"}, null);
1304                 }
1305
1306                 [Test]
1307                 public void TestBindingFlagsExactBindingC ()
1308                 {
1309                         MethodInfo method = typeof (Foo).GetMethod ("Add");
1310                         method.Invoke((new Foo ()), 0, new Int32Binder (), new object [] {1, "2"}, null);
1311                 }
1312         }
1313 }