2

I'm writing a dynamic model binder that binds functions to api calls.

This is my test controller with 2 functions. They have different functions with different parameter types.

public class MyTestController : System.Web.Mvc.Controller {

    public ActionResult MyFunction() {
        // Do awesome stuff
        return result;
    }

    public ActionResult MyOtherFunction(int i) {
        // Do other awesome stuff
        return result;
    }
}

With this model binder I want to to be able to select the specific functions and create my api call name.

public static class ModelBinder {
    public static string GetApiCall<T>( Expression<Func<T, Func<ActionResult>>> expression ) {
        var unaryExpression = (UnaryExpression)expression.Body;
        var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
        var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
        var methodInfo = (MemberInfo)methodInfoExpression.Value;

        var controllerName = typeof( T ).Name.Replace( "Controller", "" );
        var methodName = methodInfo.Name;

        var myApiCallName = string.Format( "{0}_{1}", controllerName, methodName ).ToLower();
        return myApiCallName;
    }
}

Using the ModelBinder works with functions in the controller class without parameters. But not with the parameterized function.

var apiCallName1 = ModelBinder.GetApiCall<MyTestController>( x => x.MyFunction );
var apiCallName2 = ModelBinder.GetApiCall<MyTestController>( x => x.MyOtherFunction ); // Compiler Says no!

It's not possible to compile because the function definition does not match. In this case I would need to define another GetApiCall Method with another parameter type of Expression>>.

So here's the actual question:

Is there any type in C# that accepts all kinds of delegate types, but it bound to a specific return type? So only functions that return a results of type of ActionResult.

public static string GetApiCall<T>( Expression<Func<T, MagicDelegateTypeThatTakesAllFunctionsWithAllParameterTypes>> expression ) {
    // do awesome stuff
}

Edit

Thank you @LeBaptiste for the Link. It is Possible the make the function call with the Delegate data type.

public static string GetApiCall<T>( Expression<Func<T, Delegate>> expression ) {
    // do awesome stuff
}

// Calling the method
ModelBinder.GetApiCall<MyTestController>( x => new Func<int, ActionResult>( x.MyOtherFunction ) );

Is there any way to get some sort of auto boxing this call, so I dont have to write this Func wrapper all the time?

Community
  • 1
  • 1
Arndt Bieberstein
  • 1,128
  • 1
  • 14
  • 28
  • 1
    do you need to include the param for MyOtherFunction? `x => x.MyOtherFunction(i)` – JamieD77 Aug 22 '16 at 15:57
  • No I just need the function name – Arndt Bieberstein Aug 22 '16 at 16:02
  • 2
    This looks like to answer your need: http://stackoverflow.com/questions/8225302/get-the-name-of-a-method-using-an-expression – LeBaptiste Aug 22 '16 at 17:01
  • Why do you need to care about return type in your parameter? You don't need to do `typeof(T)` when you can just get rid of the generic and do something like `expression.Body.Type`. – smead Aug 22 '16 at 19:59
  • 1
    I don't think what you originally were trying to do is possible. See [this question](http://stackoverflow.com/questions/798434/can-you-declare-a-variable-length-generics-type-declaration). This is the same reason in the .NET library you see separate defintions for `Func`, `Func`, `Func`, etc... – smead Aug 22 '16 at 20:02

0 Answers0