如何通过反射执行带有可选参数的私有静态方法?

发布于 2024-12-11 01:51:06 字数 381 浏览 0 评论 0原文

我有一个带有带有可选参数的私有静态方法的类。如何通过反射从另一个类调用它?有一个类似的问题,但它不涉及静态方法或可选参数。

public class Foo {
    private static void Bar(string key = "") {
       // do stuff
    }
}

如何调用 Foo.Bar("test")Foo.Bar() (例如,不传递可选参数)?

I have a class with a private static method with an optional parameter. How do I invoke it from another class via Reflection? There is a similar question, but it does not address static method or optional parameters.

public class Foo {
    private static void Bar(string key = "") {
       // do stuff
    }
}

How do I invoke Foo.Bar("test") and Foo.Bar() (e.g. without passing the optional parameter)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

掀纱窥君容 2024-12-18 01:51:06

C# 中的可选参数值是通过在调用站点注入这些值来编译的。即,即使您的代码是

Foo.Bar()

编译器实际上会生成一个调用,例如

Foo.Bar("")

当查找方法时,您需要将可选参数视为常规参数。

var method = typeof(Foo).GetMethod("Bar", BindingFlags.Static | BindingFlags.NonPublic);

如果您确切地知道要使用哪些值来调用该方法,则可以执行以下操作:

method.Invoke(obj: null, parameters: new object[] { "Test" });

如果您只有一些参数并且想要遵守默认参数的值,则必须检查该方法的 ParameterInfo 对象以查看参数是否可选以及这些值是什么是。例如,要打印出这些参数的默认值,您可以使用以下代码:

foreach (ParameterInfo pi in method.GetParameters())
{
    if (pi.IsOptional)
    {
        Console.WriteLine(pi.Name + ": " + pi.DefaultValue);
    }
}

Optional parameter values in C# are compiled by injection those values at the callsite. I.e. even though your code is

Foo.Bar()

The compiler actually generates a call like

Foo.Bar("")

When finding the method you need to treat the optional parameters as regular parameters.

var method = typeof(Foo).GetMethod("Bar", BindingFlags.Static | BindingFlags.NonPublic);

If you know exactly what values you want to invoke the method with you can do:

method.Invoke(obj: null, parameters: new object[] { "Test" });

If you only have some of the parameters and want to honor the values of the default ones you have to inspect the method's ParameterInfo objects to see if the parameters are optional and what those values are. For example to print out the default values of those parameters you could use the following code:

foreach (ParameterInfo pi in method.GetParameters())
{
    if (pi.IsOptional)
    {
        Console.WriteLine(pi.Name + ": " + pi.DefaultValue);
    }
}
忆梦 2024-12-18 01:51:06

使用此类

  public class Foo
  {
    private static void Bar(string key = "undefined key", string value = "undefined value")
    {
      Console.WriteLine(string.Format("The key is '{0}'", key));
      Console.WriteLine(string.Format("The value is '{0}'", value));
    }
  }

您可以使用以下代码以默认值调用它

  MethodInfo mi = typeof(Foo).GetMethod("Bar", BindingFlags.NonPublic | BindingFlags.Static);
  ParameterInfo[] pis = mi.GetParameters();

  object[] parameters = new object[pis.Length];

  for (int i = 0; i < pis.Length; i++)
  {
    if (pis[i].IsOptional)
    {
      parameters[i] = pis[i].DefaultValue;
    }
  }

  mi.Invoke(null, parameters);

如果该方法有一些非可选参数,则必须在调用该方法之前将它们插入到参数数组中。

例如,

private static void Bar(int number, string key = "undefined key", string value = "undefined")

需要您

parameters[0] = "23"

在调用之前执行以下操作

Using this class

  public class Foo
  {
    private static void Bar(string key = "undefined key", string value = "undefined value")
    {
      Console.WriteLine(string.Format("The key is '{0}'", key));
      Console.WriteLine(string.Format("The value is '{0}'", value));
    }
  }

You can use the following code to call it with the default values

  MethodInfo mi = typeof(Foo).GetMethod("Bar", BindingFlags.NonPublic | BindingFlags.Static);
  ParameterInfo[] pis = mi.GetParameters();

  object[] parameters = new object[pis.Length];

  for (int i = 0; i < pis.Length; i++)
  {
    if (pis[i].IsOptional)
    {
      parameters[i] = pis[i].DefaultValue;
    }
  }

  mi.Invoke(null, parameters);

If the method had some non-optional parameters, you will have to insert them into the parameters array before invoking the method.

E.g

private static void Bar(int number, string key = "undefined key", string value = "undefined")

Would require you to do

parameters[0] = "23"

Before invoking

冷情 2024-12-18 01:51:06

我为单元测试编写的内容:

    /// <summary>
    /// Attempts to execute a function and provide the result value against the provided source object even if it is private and/or static. Just make sure to provide the correct BindingFlags to correctly identify the function.
    /// </summary>
    /// <typeparam name="TReturn">The expected return type of the private method.</typeparam>
    /// <param name="type">The object's Type that contains the private method.</param>
    /// <param name="source">The object that contains the function to invoke. If looking for a static function, you can provide "null".</param>
    /// <param name="methodName">The name of the private method to run.</param>
    /// <param name="flags">Binding flags used to search for the function. Example: (BindingFlags.NonPublic | BindingFlags.Static) finds a private static method.</param>
    /// <param name="output">The invoked function's return value.</param>
    /// <param name="methodArgs">The arguments to pass into the private method.</param>
    /// <returns>Returns true if function was found and invoked. False if function was not found.</returns>
    private static bool TryInvokeMethod<TReturn>(Type type, object source, string methodName, BindingFlags flags, out TReturn output, params object[] methodArgs)
    {
        var method = type.GetMethod(methodName, flags);
        if(method != null)
        {
            output = (TReturn)method.Invoke(source, methodArgs);
            return true;
        }

        // Perform some recursion to walk the inheritance. 
        if(type.BaseType != null)
        {
            return TryInvokeMethod(type.BaseType, source, methodName, flags, out output, methodArgs);
        }

        output = default(TReturn);
        return false;
    }

然后像这样调用它以调用私有静态函数:

var success = TryInvokeMethod(typeof(Foo), null, "MyPrivateStaticFunc", BindingFlags.NonPublic | BindingFlags.Static, out result, arg1ToPass);

免责声明:我仅将其用于具有返回值的函数。尝试执行没有返回值的方法将引发异常。

Something i wrote for my unit tests:

    /// <summary>
    /// Attempts to execute a function and provide the result value against the provided source object even if it is private and/or static. Just make sure to provide the correct BindingFlags to correctly identify the function.
    /// </summary>
    /// <typeparam name="TReturn">The expected return type of the private method.</typeparam>
    /// <param name="type">The object's Type that contains the private method.</param>
    /// <param name="source">The object that contains the function to invoke. If looking for a static function, you can provide "null".</param>
    /// <param name="methodName">The name of the private method to run.</param>
    /// <param name="flags">Binding flags used to search for the function. Example: (BindingFlags.NonPublic | BindingFlags.Static) finds a private static method.</param>
    /// <param name="output">The invoked function's return value.</param>
    /// <param name="methodArgs">The arguments to pass into the private method.</param>
    /// <returns>Returns true if function was found and invoked. False if function was not found.</returns>
    private static bool TryInvokeMethod<TReturn>(Type type, object source, string methodName, BindingFlags flags, out TReturn output, params object[] methodArgs)
    {
        var method = type.GetMethod(methodName, flags);
        if(method != null)
        {
            output = (TReturn)method.Invoke(source, methodArgs);
            return true;
        }

        // Perform some recursion to walk the inheritance. 
        if(type.BaseType != null)
        {
            return TryInvokeMethod(type.BaseType, source, methodName, flags, out output, methodArgs);
        }

        output = default(TReturn);
        return false;
    }

Then call it like so to invoke a private static function:

var success = TryInvokeMethod(typeof(Foo), null, "MyPrivateStaticFunc", BindingFlags.NonPublic | BindingFlags.Static, out result, arg1ToPass);

Disclaimer: I use this for functions with a return value only. Attempting to execute a method with no return value will throw an exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文