[英]How to identify a lambda closure with reflection
我正在编写一个涉及Actions的组件,当Action.Target对象是编译器生成的闭包时,它就要求找到一种使用反射案例进行标识的方法。 我正在做一个实验,试图找到一种方法,这个小实验的目的是开发一个带Action的谓词,并返回一个布尔值,该布尔值告诉action目标是否是此类闭包类的实例。
在我的测试案例中,我具有以下创建4种不同类型的动作的方法:
private void _createClosure(int i)
{
ClosureAction = new Action(() =>
{
var j = i;
var k = somenum;
});
}
private void _createLambda()
{
LambdaAction = new Action(() =>
{
this._instanceAction();
});
}
private void _createInstance()
{
InstanceAction = new Action(_instanceAction);
}
private void _createStatic()
{
StaticAction = new Action(_staticAction);
}
private int somenum;
private void _instanceAction()
{
somenum++;
}
private static void _staticAction()
{
}
下表显示了每个操作的属性:
如您所见,LambaAction和ClosureAction在定义方面非常相似,它们都使用lambda,但是闭包一个具有在lambda内部使用的局部函数变量,因此编译器被迫生成闭包类。 很明显,第二行,即呈现ClosureAction的行,是唯一具有闭包类型目标的行。 静态的一个根本没有目标,而另外两个则使用调用类(Called ActionReferences)作为目标。 下表提供了目标反射类型属性的比较:
因此,我们可以看到闭包情况的独特之处在于目标类型不是类型信息,而是嵌套类型。 它也是唯一一个私有嵌套,密封且名称包含字符串+ <> c__DisplayClass的名称。 现在,尽管我认为这些特征对于任何正常使用情况都是决定性的,但我还是希望定义一个我可以依靠的谓词。 我不希望这种机制基于编译器的命名约定或不唯一的属性,因为从技术上讲,用户可能会创建具有相同命名约定的私有嵌套密封类……这不太可能,但这并不是100%干净的解决方案。
所以最后-问题是这样的:是否有一种干净的方法来编写谓词,这些谓词实际上是编译器生成的闭包的identify操作?
谢谢
这不是100%准确,但通常可以:
bool isClosure = action.Target != null && Attribute.IsDefined(
action.Target.GetType(), typeof(CompilerGeneratedAttribute));
Console.WriteLine(isClosure);
当然,您可以通过手动将[CompilerGenerated]
添加到您选择的任何类型来强制误报。
您也可以使用action.Method.DeclaringType
,但是由于所有捕获都涉及目标实例,因此保留Target
检查很有用:
bool isClosure = action.Target != null && Attribute.IsDefined(
action.Method.DeclaringType, typeof(CompilerGeneratedAttribute));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.