Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better (generic) declaration of Func delegates

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.

like image 762
Mike Avatar asked Feb 22 '23 09:02

Mike


2 Answers

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.

like image 69
Bevan Avatar answered Mar 02 '23 00:03

Bevan


"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);                      
}
like image 21
Reed Copsey Avatar answered Mar 02 '23 00:03

Reed Copsey