简体   繁体   中英

Generic function for calling back every kinds of methods with different arguments in C#

I want to have a function which is able to call any function and retrieve a proper value.

these are some examples of what I need:

var IList<Person> = InvokeFunction<IList<Person>>(repositoryPerson.GetAllPerson);

var Persion = InvokeFunction<Person>(repositoryPerson.GetPersonById, 10);

var int = InvokeFunction<int>(repositoryPerson.RunCustomStoreProcedure, 250,"text",521,10);

There is no syntax that will allow you to do that since there is no syntax that will allow you to call your InvokeFunction method and pass in the method to call as the first parameter like that.

Specifically, the only type you can declare InvokeFunction to have as its first parameter would be some kind of delegate type, but you need to specify a specific delegate type, which gets you back to square 1.

Now, what if you modified the syntax slightly, here's a LINQPad program that demonstrates:

void Main()
{
    var t = new Test();
    InvokeFunction<int>(t, "Add", 10, 20).Dump();
    InvokeFunction<int>(t, "Negate", 10).Dump();
    InvokeFunction<int>(t, "SemiRandom").Dump();
}

public class Test
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Negate(int value)
    {
        return -value;
    }

    public int SemiRandom()
    {
        return new Random().Next();
    }
}

public static T InvokeFunction<T>(object instance, string methodName, params object[] arguments)
{
    var method = instance.GetType().GetMethod(methodName, arguments.Select(a => a.GetType()).ToArray());
    return (T)method.Invoke(instance, arguments);
}

This example is missing:

  1. Error checking (null references)
  2. Null parameter handling (if the method has overloads, which one to pick?)

You can do this using reflection and generic method concpt.

Ideally you can create a generic method like below

public T InvokeFunction<T>(repositoryPerson function, params object[] parameters)
    {
        object instance = Activator.CreateInstance(typeof(RepositoryPerson));
        MethodInfo mi = instance.GetType().GetMethod(function.ToString());

        return (T)mi.Invoke(instance, parameters);

    }

An enum with all the possibile function names would be better

        enum repositoryPerson
        {
            GetAllPerson, GetPersonById, RunCustomStoreProcedure
        }

Here you can have a facade which represents all the functions for the repository

public class RepositoryPerson
    {
        public IList<Person> GetAllPerson()
        {
            //return your result
            return null;
        }
        public Person GetPersonById(int id)
        {
            //return your result
            return null;
        }
        public int RunCustomStoreProcedure(int param1, string param2)
        {
            //return your result
            return 0;
        }
    }

Now you can call your function like below

    IList<Person> persons = InvokeFunction<IList<Person>>(repositoryPerson.GetAllPerson);
    Person person = InvokeFunction<Person>(repositoryPerson.GetPersonById, 5);
    int val = InvokeFunction<int>(repositoryPerson.RunCustomStoreProcedure, 2, "3", "parame4");

Please note that this is just a concept. Definitely you have to do type check, null reference etc. while calling your actual functions.

It can be a generic function:

    public static T InvokeFunction<T>(Func<T> functionName)
    {
        T obj = functionName.Invoke();
        return obj;
    }

How to use:

   public static string method1(string a, string b)
    {
        return a + b;
    }

   public static int method2(int id1, string id2, string id3)
    {
        return 0;
    }


  var result1 = InvokeFunction<string>(() => method1("val1", "val2"));
  var result2 = InvokeFunction<int>(() => method2(123, "val1", "val2"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM