7

这是 C# 4.0。

我有一个类将 s 存储在这样WeakReference的一些Actions 上:

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稍后传递给它的 s ,但它在这个问题中并不重要。

我以这种方式消费这个类:

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. action我在(like IsAbstract)上找不到任何属性IsAnonymous。底层类型是MethodInfo有意义的,因为编译后我可以在 ildasm 中看到匿名方法“成为” Foobar. 在 ildasm 中,我还可以看到匿名方法不是一个完整的粉红色方块,而是一个被粉红色包围的白色方块,并且在其定义中调用了一些 CompilerServices 类,但我不知道如何在 C# 中利用这一点。我相信有可能了解action. 我错过了什么?

4

2 回答 2

4

为了对这个问题有一个“接受”的答案,我按照 Michael Kjörling 在他对我的问题的第一条评论中给出的链接进行了操作。

if (action.Target.GetType().GetMethods().Where(method => method.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any()).Contains(action.Method))
{
    // ...
}
于 2012-10-15T17:41:38.483 回答
2

编译器生成的方法的名称总是带有尖括号,如下所示

Void <Main>b__0()

那么为什么不直接获取名称并查看它是否包含尖括号。

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

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

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

于 2012-10-06T09:09:28.480 回答