我有一个私有(private)静态泛型方法,我想使用反射来调用,但实际上我想将其“ bundle ”在另一个方法中。 C#7.0支持本地功能,因此这绝对是可能的。

您会说“为什么不直接打电话呢?”但是我正在使用它来获得以强类型方式使用对象和System.Type的功能,因此我需要动态调用它。如果我有此代码,则该代码已经可以使用,因为它是自己的私有(private)静态泛型方法。

private static void HandleResponse(object data, Type asType)
{
    var application = typeof(Program);

    application
        .GetMethod(nameof(UseAs), BindingFlags.Static | BindingFlags.NonPublic)
        .MakeGenericMethod(asType)
        .Invoke(null, new object[] { data });
}

public static void UseAs<T>(T obj)
{
    Console.WriteLine($"Object is now a: {typeof(T)}:");
};

上面的代码有效。如果我通过:
data: new TestObject(),
type: typeof(TestObject)

我实际上将在UseAs中有一个TestObject。

因此,我想将所有这些都放在一个方法中,如下所示:
private static void HandleResponse(object data, Type asType)
{
    void useAs<T>(T obj)
    {
        Console.WriteLine($"Object is now a: {typeof(T)}:");
    };

    var application = typeof(Program);

    application
        .GetMethod(nameof(UseAs), BindingFlags.Static | BindingFlags.NonPublic)
        .MakeGenericMethod(asType)
        .Invoke(null, new object[] { data });
}

不幸的是,GetMethod代码不再起作用。我听说在编译时,编译器会将任何本地函数转换为静态方法,因此我跳到立即窗口并运行:
application.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)

...而且,我实际上确实看到了以下响应:
{System.Reflection.MethodInfo[3]}
    [0]: {Void Main(System.String[])}
    [1]: {Void HandleResponse(System.Object, System.Type)}
    [2]: {Void <HandleResponse>g__useAs1_0[T](T)}

这是列表上的最后一个方法。有谁知道您将如何以合理的方式访问类似的方法?

谢谢!

编辑:

我确实可以将UseAs用作普通的私有(private)静态方法。它只是不会在其他任何地方使用,所以我想将其全部打包在一个方法中。

另外,这实际上应该是一个关于查找局部函数的问题,而在StackOverflow上的其他任何地方似乎都没有这个问题。我发现很难相信,至少在某些时刻,某人不会对此感到好奇。

首先,我很犹豫是否提供任何代码,因为我只是想修改一个主意,但是我想要实现的实际目标完全是这个问题的第二要务。

最佳答案

好的,我有解决方案。但这真的很可怕。它涉及从具有特定类型的方法中创建委托(delegate),然后使用该委托(delegate)找到通用方法,然后构造另一个特定方法并调用它。

因此,我们从UseAs<int>UseAs<T>UseAs<the-type-we-want>

在许多方面,它可能会导致严重的错误,但是它仅适用于我测试过的非常有限的示例:

// DISCLAIMER: THIS CODE IS FAIRLY HACKY, AND MAY WELL FAIL IN WEIRD
// SITUATIONS. USE WITH EXTREME CAUTION AND LOTS OF TESTS!

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        HandleResponse("foo", typeof(string));
    }

    static void HandleResponse(object data, Type type)
    {
        string local = "This was a local variable";
        void UseAs<T>(T obj)
        {
            Console.WriteLine($"Object is now a: {typeof(T)}:");
            // Proof that we're capturing the target too
            Console.WriteLine($"Local was {local}");
        }

        InvokeHelper(UseAs, data, type);
    }

    // This could be in any class you want
    static void InvokeHelper(Action<int> int32Action, object data, Type type)
    {
        // You probably want to validate that it really is a generic method...
        var method = int32Action.Method;
        var genericMethod = method.GetGenericMethodDefinition();
        var concreteMethod = genericMethod.MakeGenericMethod(new[] { type });
        concreteMethod.Invoke(int32Action.Target, new[] { data });
    }
}

关于c# - 反射(reflection):如何在C#7.0中查找和调​​用局部函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43348128/

10-13 05:53