Reflection: How do I find and invoke a local functon in C# 7.0?

不想你离开。 提交于 2019-12-03 23:23:21

Okay, I've got a solution. But it's really horrible. It involves creating a delegate from your method with a specific type, then using that to find the generic method, then constructing another specific method and invoking it.

So we go from UseAs<int> to UseAs<T> to UseAs<the-type-we-want>.

It could go horribly wrong in many ways, but it works for the very limited sample I've tested:

// 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 });
    }
}

Calling a local function with reflection is like looking for trouble. The name isn't "fixed". It changes based on how many other local functions there are in the same class... So if you modify another method you could change the name of the local function you are interested in.

You can take a look at this TryRoslyn.

There are three classes, Class1, Class2 and Class3. They all have a method M that internally has a local function Test. Class1 and Class2 are identical to the last character. The local method is then compiled to a method named <M>g__Test0_0(). Class3 introduces before the M method another method, Filler, with another local function (Foo) that is then compiled to <Filler>g__Foo0_0. In this case the local method of M is named <M>g__Test1_0().

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!