Bre*_*use 15 c# reflection methods system.reflection
我有一个我想用反射调用的私有静态泛型方法,但实际上我想在另一个方法中"捆绑"它.C#7.0支持本地功能,所以这绝对是可能的.
你会说"你为什么不直接叫它?" 但我正在用它来获得以强类型方式使用对象和System.Type的能力,所以我需要动态调用它.如果我将它作为自己的私有静态泛型方法,则此代码已经有效.
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)}:");
};
Run Code Online (Sandbox Code Playgroud)
上面的代码有效.如果我通过:
data: new TestObject(),
type: typeof(TestObject)
Run Code Online (Sandbox Code Playgroud)
我实际上在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 });
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,GetMethod代码不再有效.我听说在编译时编译器将任何本地函数转换为静态方法,因此我弹出到即时窗口并运行:
application.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
Run Code Online (Sandbox Code Playgroud)
......而且,我实际上看到了这个回应:
{System.Reflection.MethodInfo[3]}
[0]: {Void Main(System.String[])}
[1]: {Void HandleResponse(System.Object, System.Type)}
[2]: {Void <HandleResponse>g__useAs1_0[T](T)}
Run Code Online (Sandbox Code Playgroud)
这是列表中的最后一个方法.有没有人知道如何以合理的方式访问这样的方法?
谢谢!
编辑:
我确实可以将UseAs用作普通的私有静态方法.它不会在其他任何地方使用,所以我想在一个方法中"打包"它.
另外,这实际上应该是关于一般地查找本地函数的问题,并且在StackOverflow上的任何其他地方似乎都没有关于它的问题.我觉得很难相信,在某些方面,至少有人不会好奇这样做.
我首先提供任何代码都犹豫不决,因为我只想修改一个想法,但我想要完成的实际目标完全是问题的次要问题.
好的,我有一个解决方案.但它真的太可怕了.它涉及使用特定类型从方法创建委托,然后使用它来查找泛型方法,然后构造另一个特定方法并调用它.
因此,我们从去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 });
}
}
Run Code Online (Sandbox Code Playgroud)
用反射调用本地函数就像找麻烦一样.该名称不是"固定的".它会根据同一个类中有多少其他本地函数而改变...因此,如果您修改另一个方法,则可以更改您感兴趣的本地函数的名称.
你可以看看这个TryRoslyn.
有三个类Class1,Class2和Class3.它们都有一个M内部具有本地功能的方法Test.Class1并且Class2与最后一个字符相同.然后将本地方法编译为名为的方法<M>g__Test0_0().Class3在M方法之前引入另一个方法,然后Filler使用另一个本地函数(Foo)进行编译<Filler>g__Foo0_0.在这种情况下,本地方法M被命名<M>g__Test1_0().
| 归档时间: |
|
| 查看次数: |
2403 次 |
| 最近记录: |