【问题标题】:Call a function with unknown type and number of parameters in C#在 C# 中调用具有未知类型和参数数量的函数
【发布时间】:2012-01-09 14:21:28
【问题描述】:

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

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

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

谢谢

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

【问题讨论】:

  • 无论如何你会为参数传递什么参数?如果您可以提供有关上下文的更多信息,那将使生活变得更加轻松。
  • 请详细介绍一下上下文。如果您或人们不知道方法的签名,他们将如何使用它?看起来好像很容易出错并传递不正确的变量。如果您有权访问这些类,为什么您无法提取定义?
  • @Jon Skeet:您可以假设我将为每个参数提供默认值,或者假设参数在有限的已知集合内,并且对于每种类型,我都有一个创建值的过程那种类型。
  • @oleksii:在运行时并使用反射,我可以获得每个方法的签名作为“MethodInfo”,其中包含有关方法名称和类型以及每个参数类型的信息.事实上,我正在编写一个模拟器程序,使用我的程序的人将编写一个包含一些方法的类(并为每个方法定义一些属性),在运行时,我编译代码并获取有关每个方法的信息并然后,调用其中一些方法。

标签: c# delegates


【解决方案1】:

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

例如,一旦您拥有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 实际调用该方法。

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

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

【讨论】:

  • 是的,但问题是如何使用从反射中获得的信息来调用这些方法
【解决方案2】:

我提供的代码适用于您提供的 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;
}

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 2022-01-16
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2015-06-14
    相关资源
    最近更新 更多