在C#中调用具有未知类型和参数数量的函数

时间:2012-01-08 22:43:12

标签: c# delegates

我正在用C#编写一个库,我必须调用其他程序员在他们的类中定义的一些方法,所以我不知道参数的类型和数量。例如,

Class exampleClass{
    void method1(int param1, double param2){...}
    bool method2(){...}
    object method3(string param1){....}
}

在我的程序中,我想调用这些方法。由于我不知道他们的参数和返回类型,我不能使用“委托”(已知类型和参数),但在运行时,我可以使用,例如,反射来提取来自类的方法及其参数(“ MethodInfo ”)但如何使用此信息来调用方法? (假设我可以生成适当的值作为方法的参数)。

由于

PS:我知道“params object []”方法,但它会强制程序员使用“params”对象,而不是在他们的方法中定义它们的常用参数。所以,我不想使用这种方法。

2 个答案:

答案 0 :(得分:7)

您可以使用反射来获取有关方法的所有信息。

例如,如果您拥有MethodInfo,则可以获得ReturnType

Type MyType = Type.GetType("System.Reflection.FieldInfo");
MethodInfo Mymethodinfo = MyType.GetMethod("GetValue");

Console.Write ("\n" + MyType.FullName + "." + Mymethodinfo.Name);
Console.Write ("\nReturnType = {0}", Mymethodinfo.ReturnType);

GetParameters会告诉您参数:

Type delegateType = typeof(MainClass).GetEvent("ev").EventHandlerType;
MethodInfo invoke = delegateType.GetMethod("Invoke");
ParameterInfo[] pars = invoke.GetParameters();
foreach (ParameterInfo p in pars) 
{
    Console.WriteLine(p.ParameterType);
}

获得此信息后,您可以使用Invoke实际调用该方法。

它的第一个参数是“调用方法的对象”。

它的第二个参数是所述方法的参数列表。

答案 1 :(得分:1)

我提供的代码与您提供的ExampleClass一起使用,但绝不是一个完整的解决方案。你需要考虑泛型,参考,参数,以及可能还有很多其他的东西。

public void CallAllMethods(object instance)
{
    foreach (MethodInfo method in instance.GetType().GetMethods())
    {
        if (method.IsGenericMethod || method.DeclaringType == typeof(object))
        {
            // skipping, System.Object method or a generic method
            continue;
        }

        var defaultParamValues = method.GetParameters().Select(p => GetDefaultValue(p.ParameterType)).ToArray();
        Console.WriteLine("Invoking {0} with param values {1}", method.Name, string.Join(", ", defaultParamValues));
        object retVal = method.Invoke(instance, defaultParamValues);

        if (method.ReturnType != typeof(void))
        {
            Console.WriteLine("  and returned a value of {0}", retVal);
        }
    }
}

public static object GetDefaultValue(Type type)
{
    return type.IsValueType ? Activator.CreateInstance(type) : null;
}
相关问题