如何知道Action是否是匿名方法?

时间:2012-10-06 08:21:56

标签: c# delegates anonymous-methods

这是C#4.0。

我有一个类WeakReference存储Action的类:

public class LoremIpsum
{
    private Dictionary<Type, List<WeakReference>> references = new Dictionary<Type, List<WeakReference>>();

    public void KeepReference<T>(Action<T> action)
    {
        if (this.references.ContainsKey(typeof(T)))
        {
            this.references[typeof(T)].Add(new WeakReference(action));
        }
        else
        {
            this.references.Add(typeof(T), new List<WeakReference> { new WeakReference(action) });
        }
    }
}

这个类有另一个允许执行稍后传递给它的Action的方法,但在这个问题上它并不重要。

我以这种方式使用这个类:

public class Foobar
{
    public Bar Bar { get; set; }

    public void Foo(LoremIpsum ipsum)
    {
        ipsum.KeepReference<Bar>((b) => { this.Bar = b; });
        ipsum.KeepReference<Bar>(this.Whatever);
    }

    public void Whatever(Bar bar)
    {
        // Do anything, for example...:
        this.Bar = bar
    }
}

Bar是我申请中的第三堂课。

我的问题:

KeepReference方法中,我如何知道参数中传递的Action是指匿名方法(this.Bar = b;)还是具体方法( this.Whatever)?

我检查了action的属性。我在actionIsAbstract(例如IsAnonymous)上找不到任何属性。基础类型是MethodInfo这是有道理的,因为在编译后我可以在ildasm中看到匿名方法“成为”Foobar上的常规方法。在ildasm我也可以看到匿名方法不是一个完整的粉红色正方形,而是一个被粉红色包围的白色方块,在它的定义中,它调用了一些CompilerServices类,但我不知道如何在C#中利用它。我确信有可能了解action的真实性质。我错过了什么?

2 个答案:

答案 0 :(得分:3)

为了在这个问题上得到“接受”的答案,我按照MichaelKjörling在我关于我的问题的第一条评论中给出的链接去了。

if (action.Target.GetType().GetMethods().Where(method => method.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any()).Contains(action.Method))
{
    // ...
}

答案 1 :(得分:2)

编译器生成的方法的名称将始终带有角度括号,如下所示

Void <Main>b__0()

所以为什么不只是获取名称,看看它是否有角度括号。

Action someaction = () => Console.Write("test");
string methodName= RuntimeReflectionExtensions.GetMethodInfo(someaction).ToString();

if(methodName.Contains("<"))
  Console.write("anonymous");

或者您可以使用与正则表达式更好的模式匹配