Reputation: 2012
ok, I hope the title of this question makes sense. In my app I have some methods which should be invoked by a special InvokeMethod. At the moment, it works like this:
internal bool RemoteLogin(string password)
{
return (bool)InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password);
}
internal string GetSessionId()
{
return (string)InvokeMethod(new Func<string>(Server.GetSessionId));
}
public object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
To call InvokeMethod I have to pass a new Func<....>, add the parameter(s) and also cast the return value to the appropriate type. Is there a better (more generic) way to do this, for example using Generics or Reflection?
Any help is highly appreciated.
Upvotes: 4
Views: 575
Reputation: 2012
Additional Info: If a method has no return value (e.g. "void Logout()" ), you can use the Action delegate (method can have thesame name -> InvokeMethod -> because of the different signature/parameter):
public void InvokeMethod(Action method)
{
method();
}
Upvotes: 1
Reputation: 44317
You can achieve a certain amount of strong typing - at the expense of repetition by using Func
variations:
public R InvokeMethod<T,R>(Func<T,R> method, T argument)
{
return method(argument);
}
public R InvokeMethod<T1,T2,R>(Func<T1,T2,R> method, T1 argument1, T2 argument2)
{
return method(argument1, argument2);
}
public R InvokeMethod<T1,T2,T3,R>(Func<T1,T2,T3,R> method, T1 argument1, T2 argument2, T3 argument3)
{
return method(argument1, argument2, argument3);
}
And so on.
Though this is consistent with your original, there's no actual need to handle parameters at all. Try writing your InvokeMethod
this way:
public R InvokeMethod<R>(Func<R> method)
{
return method();
}
and then call it with this style:
internal bool RemoteLogin(string password)
{
return InvokeMethod(() => Server.RemoteLogin(password));
}
internal string GetSessionId()
{
return InvokeMethod( () => Server.GetSessionId());
}
This way, you leave the parameter handling to the lambda expression and you only need to write InvokeMethod once.
Upvotes: 3
Reputation: 3752
static T Invoke<T>(Func<T> method)
{
//Log here
return method();
}
bool RemoteLogin(string password)
{
return Invoke(() => Server.RemoteLogin(password));
}
Upvotes: 1
Reputation: 564781
"In my example above, the method InvokeMethod is simplified. In my app it does log, monitor, exception handling etc. of an invocation."
Given this comment, my suggestion would be to rework this. Instead of invoking the delegate as this, you could make the operation take Func<T>
, like so:
public T InvokeMethod<T>(Func<T> method)
{
// Add wrapper as needed
return method();
}
You could then call it using lambdas when you need to pass parameters:
internal bool RemoteLogin(string password)
{
return InvokeMethod(() => Server.RemoteLogin(password));
}
internal string GetSessionId()
{
return InvokeMethod(Server.GetSessionId);
}
Upvotes: 2
Reputation: 22168
I agree with Reed that you really could just call the method directly and eliminate some redundant code, but if you want that strong typing when you are doing these things, it's very easy to rewrite the InvokeMethod
call like so.
public static T InvokeMethod<T>(Delegate method, params object[] args)
{
return (T)method.DynamicInvoke(args);
}
Then your call above just becomes:
return InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password);
And the Boolean
return type is inferred by the return type on your method.
Upvotes: 1