The following F#
code fails because Type.DefaultBinder
does not want to bind to the generic Id
method. Is there an alternative Binder
that would do this?
open System
open System.Reflection
type Foo() =
member this.Id<'T>(x: 'T) : 'T = x //'
typeof<Foo>.InvokeMember (
"F",
BindingFlags.InvokeMethod,
Type.DefaultBinder,
(new Foo()),
[| box "test" |]
)
Here is equivalent C#:
using System;
using System.Reflection;
public class Foo {
T Id<T>(T x) {
return x;
}
static void Main() {
typeof(Foo).InvokeMember
(
"F",
BindingFlags.InvokeMethod,
Type.DefaultBinder,
(new Foo()),
new object[] {"test"}
);
}
}
The note under "Remarks" on the InvokeMember page indicates that InvokeMember cannot be used to invoke a generic method. Presumably this related to the fact that you can't use typeof<Foo>.GetMethod("Id").Invoke(...)
either, since you need to specify a generic parameter somehow.
On the other hand, it looks like you can probably hack something together that has a shot at working:
type MyBinder() =
inherit System.Reflection.Binder() with
let bnd = System.Type.DefaultBinder
override x.SelectProperty(a,b,c,d,e) = bnd.SelectProperty(a,b,c,d,e)
override x.ChangeType(a,b,c) = bnd.ChangeType(a,b,c)
override x.BindToField(a,b,c,d) = bnd.BindToField(a,b,c,d)
override x.ReorderArgumentArray(a,b) = bnd.ReorderArgumentArray(&a,b)
override x.SelectMethod(a,b,c,d) = bnd.SelectMethod(a,b,c,d)
override x.BindToMethod(a,meths,args,b,c,d,e) =
try
bnd.BindToMethod(a,meths,&args,b,c,d,&e)
with _ ->
let [| meth |],[| arg |] = meths,args
upcast (meth :?> System.Reflection.MethodInfo).MakeGenericMethod([| arg.GetType() |])
This handles only non-overloaded generic methods with a single argument, but you could attempt to make it more robust. I wouldn't be surprised if this implementation of BindToMethod breaks all kinds of expected invariants, though, since it returns a method which was not passed in as a candidate.