2

I am calling methods on a remote system. The remote system implements an interface that both systems have a copy of (via shared nuget repository). At the moment i am sending the requests like this:

var oldRequest = new FooRequest("GetEmployeeById", new object[] { "myPartner", 42, DateTime.Now.AddDays(-1) });

Here is the interface:

public class FooResponse<T> { }

public interface IFooController
{
    FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}

As you can image, sometimes programmers passes arguments in the wrong order to the array in the constructor, and things start to fail. To resolve this I have created the following code to have intellisense support when creating the FooRequest:

public static FooRequest Create<T>(Func<FooResponse<T>> func)
{
    return new FooRequest(null, null); // Here goes some magic reflection stuff instead of null.
}

It is now possible to create a FooRequest like this:

public static IFooController iFooController => (IFooController)new object();
public static FooRequest CreateRequest<T>(Func<FooResponse<T>> func)
{
    return FooRequest.Create(func);
}

var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));

My question then is: How will i be able to get the name of the method and the value of the parameters in the FooRequest.Create-method?

I have exhausted both my reflection and google-skills trying to find the values, but no luck so far.

Complete compiling code can be found here if someone wants to give it a shot: http://ideone.com/ovWseI

Espo
  • 41,399
  • 21
  • 132
  • 159
  • 1
    Are you familiar with `Expression`s? – default Sep 30 '16 at 11:20
  • Not enough to know how they will help me in this case. – Espo Sep 30 '16 at 11:21
  • Am a bit rusty on it as well, but I have seen implementations for INotifyPropertyChanged where using expressions are used to get the property name of the passed Func. I thought maybe there could be something to fetch from that. An implementation of it is shown [here](http://stackoverflow.com/questions/3191536/how-to-raise-propertychanged-event-without-using-string-name) – default Sep 30 '16 at 11:24
  • Although, that might be for properties only.. Maybe that doesn't help at all. – default Sep 30 '16 at 11:24

1 Answers1

2

Here is a sketch of how you can do this with expressions:

public class Test {
    public static IFooController iFooController => (IFooController) new object();

    public static FooRequest CreateRequest<T>(Expression<Func<FooResponse<T>>> func) {
        return FooRequest.Create(func);
    }

    public static void Main() {
        var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
        Console.ReadKey();
    }
}

public class FooRequest {
    public static FooRequest Create<T>(Expression<Func<FooResponse<T>>> func) {
        var call = (MethodCallExpression) func.Body;
        var arguments = new List<object>();
        foreach (var arg in call.Arguments) {
            var constant = arg as ConstantExpression;
            if (constant != null) {
                arguments.Add(constant.Value);
            }
            else {
                var evaled = Expression.Lambda(arg).Compile().DynamicInvoke();
                arguments.Add(evaled);
            }
        }
        return new FooRequest(call.Method.Name, arguments.ToArray());
    }

    public FooRequest(string function, object[] data = null) {
        //SendRequestToServiceBus(function, data);
        Console.Write($"Function name: {function}");
    }
}

public class FooResponse<T> {
}

public interface IFooController {
    FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}
Evk
  • 98,527
  • 8
  • 141
  • 191