We are creating a configuration API for some of our internal projects. The API is replacing an attribute-based configuration. The new API involves specifying methods within a class along with the options that go with it.
public static class Configuration<T> {
public static void ForMethod(Expression<Action<T>> methodExpression, Options options) { //Option-1
MethodInfo method = GetMethod(methodExpression);
// do something with options
}
public static void ForMethod<TResult>(Expression<Func<T,TResult>> methodExpression, Options options) { //Option-2
MethodInfo method = GetMethod(methodExpression);
// do something with options
}
private static MethodInfo GetMethod(Expression expression) {
// there's other checks done, but this is what it boils down to
var methodCall = (MethodCallExpression) expression.Body;
return methodCall.Method;
}
}
class MyClass {
void MyMethod() { ... }
}
Configuration<MyClass>.ForMethod(x => x.MyMethod(), ... );
This is great except for when the methods themselves have parameters. IE
class MyClass2 {
void MyMethod2(int x) { }
int SomeOtherMethod(int x) { return x*x; }
}
These can be handled by expanding the configuration class like:
public static void ForMethod<TResult, TIn>(Expression<Func<T,TIn,TResult>> methodExpression, ...) { //Option-3
}
// and then called:
Configuation<MyClass2>.ForMethod<int,int>((x,y) => x.SomeOtherMethod(y), ...);
As more parameters get added it becomes a bit more clumsy. Technically we don't care about the parameters themselves, so long as we select the correct method. We could get around this by simply specifying everything as Option-1 (since we can also ignore the return type and specify everything as Actions) and just specifying the parameters using the default
keyword, ie:
Configuration<MyClass2>.ForMethod(x => x.SomeOtherMethod(default(int)), ...)
However, this gets quite ugly.
Is there any way with type inference (or some other magic) to select the appropriate method without needing to explicitly state the parameter types? My hope would be something like this (although this do not work)
Configuration<MyClass2>.ForMethod((x,y) => x.SomeOtherMethod(y), ...) // Option 3 with return type and type of input inferred
or even
Configuration<MyClass2>.ForMethod((x,y) => x.SomeOtherMethod, ...) // Option 3 with return type and input 1 inferred + as method group
My gut tells me that this is not possible as I haven't been able to find any way around this online. My hope is that perhaps with a combination of extension methods and type inference this could be made possible, but I'm having difficulty finding anything that compiles. Is this even possible?