0

In the following piece of code, the Read method is supposed to take a function and run it by some simple rules:

public static void Read(Delegate handler)
{
    var values = new List<object>();
    foreach (var param in handler.Method.GetParameters())
    {
        Console.WriteLine($"{param.Name} : {param.ParameterType}");
        if (param.ParameterType == typeof(string))
        {
            values.Add(param.Name);
        }
        else
        {
            values.Add(null);
        }
    }

    handler.DynamicInvoke(values);
}

And here is a simple function to call:

public static void MyFunc(string p1, string p2)
{
    Console.WriteLine("Actual function");
}

But this code is compile error:

public static void Main(string[] args)
{
    Read(MyFunc);
}

And the error is:

Argument 1: cannot convert from 'method group' to 'Delegate'

I thought Delegate can be used to represent a function type. Why compiler cannot convert my function type to a Delegate?

alisabzevari
  • 8,008
  • 6
  • 43
  • 67
  • Well your passing the base delegate class as an argument pretty sure you need to declare a type of delegate that has the same signature as the MyFunc then use that as the parameter for Read. – 580 Jun 16 '18 at 22:06
  • I am looking for a type for my parameter to match every function. because I would like to run the function (and provide values for its parameters) in runtime. – alisabzevari Jun 16 '18 at 22:10
  • What is it you are actually trying to achieve, i mean this is a very unusual requirement. is there some specific problem you are trying to solve? – TheGeneral Jun 16 '18 at 23:32
  • I am trying to understand how controller actions in asp.net mvc work. You are almost free for the parameters of actions in controller and framework finds out how to provide values for arguments and call them. @thegeneral – alisabzevari Jun 17 '18 at 08:24

1 Answers1

0

You just need to create a type of delegate with the same signature of the method that will be passed into the method accepting the delegate. I wouldn't use the base Delegate type for this, create your own delegate type.

MSDN - How to: Declare, Instantiate, and Use a Delegate (C# Programming Guide)


See this post for information about the Delegate type.

Stack Overflow - Delegate vs delegate

From http://msdn.microsoft.com/en-us/library/system.delegate.aspx: The Delegate class is the base class for delegate types. However, only the system and compilers can derive explicitly from the Delegate class or from the MulticastDelegate class. It is also not permissible to derive a new type from a delegate type. The Delegate class is not considered a delegate type; it is a class used to derive delegate types.Most languages implement a delegate keyword, and compilers for those languages are able to derive from the MulticastDelegate class; therefore, users should use the delegate keyword provided by the language.


Update

As per your comment I looked into this a bit further. I believe your issue is that you need to convert the method to some form of delegate before passing it such as an Action, Func or anonymous method. I still don't think it is possible to just make a generic method which just accepts all possible inputs and outputs directly from a method. It will need to first be converted into a delegate compatible variable, then the variable will need to be passed. Hopefully, this works for what you need to do.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Display the contents of any method.
        Action<string> prntAct = TestMethod;
        PrintDelegate(prntAct);

        Action<string, string> prntAct2 = TestMethod2;
        PrintDelegate(prntAct2);

        Console.ReadKey();
    }

    public static void TestMethod(string xyz)
    {
        Console.WriteLine("Some random work to do.");
    }

    public static void TestMethod2(string abc, string def)
    {
        Console.WriteLine("Some other random work to do.");
    }

    private static void PrintDelegate(Delegate del)
    {
        var values = new List<object>();
        foreach (var param in del.Method.GetParameters())
        {
            Console.WriteLine($"{param.Name} : {param.ParameterType}");
            if (param.ParameterType == typeof(string))
            {
                values.Add(param.Name);
            }
            else
            {
                values.Add(null);
            }
        }
    }
}
580
  • 470
  • 2
  • 12
  • Actually, I know all of information you put in your answer. Even collection of object as argument (`delegate void AnyRequestDelegate(object[] parameters);`) didn't work for me. – alisabzevari Jun 16 '18 at 22:32
  • I'll look into this for a little bit now see if I can get something for you. – 580 Jun 17 '18 at 01:08
  • @alisabzevari please check and see if this update is roughly what you're looking for. – 580 Jun 17 '18 at 17:30