3

I have a generic function CallLater that should accept an arbitrary other function and possibly call it later with some parameters. All kind of functions should be supported - static, instance, private, public. Parameters are analyzed and constructed dynamically in CallLater with the help of reflection. However, some of them may need to be bound to fixed values before passing the function to the CallLater.

For example:

void CallLater(Delegate d) {
  // Expects a function that returns string and has one argument of arbitrary type.
  if (d.Method.GetParameters().Length == 1 && 
      d.Method.ReturnType == typeof(string)) {
    object param1 = Activator.CreateInstance(d.Method.GetParameters()[0].ParameterType);
    Console.WriteLine((string)d.DynamicInvoke(param1));
  }
}

// Has one extra float parameter.
string MyFunc(int a, float b) { ... }

My idea was to do something like that:

float pi = 3.14f;
CallLater(delegate(int a) { return MyFunc(a, pi); });

But this doesn't work as compiler complains:

Error CS1660: Cannot convert `anonymous method' to non-delegate type `System.Delegate' (CS1660) (test-delegate)

What is the correct approach to achieve my goal?

P.S. Please do not offer the solution to declare a fixed delegate type as CallLater is way more complex and may support variable number of arguments too.

P.P.S. It might be that my solution is Func, but I wasn't able to use it on Mono so far.

Sergiy Belozorov
  • 5,856
  • 7
  • 40
  • 73

2 Answers2

1

You can always redeclare Func yourself:

public delegate TReturn FFunc<TArg,TReturn>(TArg arg);

Which you can use thusly:

float pi = 3.14f;
CallLater((FFunc<int,string>)(delegate(int a) { return MyFunc(a, pi); }));
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • This seems to be limited to one parameter only. CallLater should be able to accept an arbitrary number of parameters. Do I need to change the declaration of CallLater or will Delegate parameter type work fine? – Sergiy Belozorov Apr 03 '13 at 21:43
  • Ooooh, you really want to research "currying" then, as someone else mentioned; I thought based on the comments inside the method you were just looking for this use case. – JerKimball Apr 03 '13 at 21:57
0

I'd suggest using anonymous functions in which you call the method you want to execute. These are executed later when the anonymous method is executed.

private static void ExecuteBoolResult(Func<bool> method)
{
    bool result = method();
    if (!result)
    {
        throw new InvalidOperationException("method did not return true");
    }
}

CheckBoolResult(() => AnotherFunction("with ", 3, " parameters"));
CheckBoolResult(() => AnotherFunction(2, "parameters"));
Wouter
  • 2,170
  • 1
  • 28
  • 58