Is there a way to use either System.CodeDom
or the Roslyn API to resolve an overloaded method call from code? At runtime, I have a method name and a list of parameters, I want to find the method the compiler would have picked at compile time.

- 37,241
- 25
- 195
- 267

- 8,579
- 8
- 51
- 90
-
And once you had the answer, what would you do it in? Also, what form is your list of parameters in? – Jason Malinowski Oct 20 '14 at 22:29
-
@JasonMalinowski My parameter list is an array of types. I'm looking for a way to force runtime method binding in VB to solve [this problem](http://stackoverflow.com/q/26470484/794234). I could write the code to perform the resolution myself (w/ reflection), but the rules are complex and it seems silly to reinvent the wheel. – just.another.programmer Oct 21 '14 at 06:30
-
1I wonder if it's possible to use the `dynamic` infrastructure directly to do this. – SLaks Oct 21 '14 at 12:13
-
Do you actually need to do full overload resolution? Wouldn't something like the following C# work: `typeof(YourType).GetMethod(name, parameterTypes)`? – svick Oct 21 '14 at 15:16
-
@SLaks VB does not support `dynamic` directly. It uses its own late binding system (using `Object` and `Dim` with no type specified). As of now, MS has decided not to add support for C# style dynamic binding to VB. – just.another.programmer Oct 21 '14 at 16:54
-
@svick That's an interesting idea, I need to test it and get back to you. – just.another.programmer Oct 21 '14 at 16:54
-
@just.another.programmer: No; I mean to manually write the code that the C# compiler generates and use the runtime `dynamic` support to do overload resolution. (assuming you don't care about the subtle differences between C# overload resolution & VB overload resolution) – SLaks Oct 21 '14 at 17:02
-
@svick: `GetMethod()` is much stricter than overload resolution; it requires exactly-matching argument types, and won't do implicit conversions, optional parameters, paramarrays, and other things. – SLaks Oct 21 '14 at 17:03
-
@SLaks Yes, I'm aware of that, but it's not clear to me from the question whether all that is actually necessary here or not. – svick Oct 21 '14 at 17:27
-
@SLaks Do you mean the IL the C# compiler generates? I wouldn't even know where to start with that. – just.another.programmer Oct 21 '14 at 18:37
-
@svick I did the test, SLaks is right. I need the implicit conversions. – just.another.programmer Oct 21 '14 at 18:38
-
1@just.another.programmer: Open compiled `dynamic` code in a decompiler with dynamic disabled. – SLaks Oct 21 '14 at 18:41
-
http://tryroslyn.azurewebsites.net/#K4Zwlgdg5gBAygTxAFwKYFsDcAoADsAIwBswBjGUogQxBBgGEYBvbGNmfYsmANwHswAExgBZABQBKZtgCQMwQghV03AB4wAvDABEVbTnaGdegHQAlVLmqlUY1QBoYqiQfYBfbG6A – SLaks Oct 21 '14 at 18:42
1 Answers
As @SLaks and @just.another.programmer suggested it is possible to exploit C# dynamic infrastructure. But it's really not straightforward nor simple. I was gazing into decompiled code for couple of hours to find following magic code. And I don't understand it completely. In the first step Binder
class is created, with parameter options set to use compile time types.
In the second magic step, the binder is called with the actual parameters. Each parameter has its value (null, its not used when UseCompileTimeType
is set) and their expression. If you know types instead of expression, use Expression.Parameter(yourType)
to substitute them.
public static Expression GetInvokeMemberExpression(Expression expr, string name, Expression[] arguments)
{
var type = expr.Type;
var argTypes = arguments.Select(e => e.Type).ToArray();
// do magic #1
var binder = (DynamicMetaObjectBinder)Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None, name,
Type.EmptyTypes, // type arguments
typeof(object),
Enumerable.Repeat(0, argTypes.Length + 1).Select(_ => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)).ToArray());
// do magic #2
var result = binder.Bind(DynamicMetaObject.Create(null, expr), arguments.Select(a => DynamicMetaObject.Create(null, a)).ToArray());
var resultMethodCall = (result.Expression as UnaryExpression).Operand as MethodCallExpression; // unwrap convert to ebject expression
var method = resultMethodCall.Method;
return resultMethodCall;
}
I was trying similar piece of code in DotVVM framework, but I haven't found a way how to "inject" custom implicit conversions, so I wrote a simple method overload recognition function. But we are still using dynamic for operators. You can find the code on github

- 452
- 3
- 12