Вопрос

This is C# 4.0.

I have a class that stores WeakReferences on some Actions like that:

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

This class has another method allowing to execute the Actions passed to it later but it's of little importance in this question.

and I consume this class this way:

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 being a third class in my application.

My question:

In the KeepReference method, how can I know if the Action passed in parameter refers to an anonymous method (this.Bar = b;) or a concrete method (this.Whatever)?

I checked the properties of action. I couldn't find any property on action (like IsAbstract) of a IsAnonymous kind. The underlying type is MethodInfo which makes sense because after compiling I can see in ildasm the anonymous method "became" a normal method on Foobar. In ildasm I can also see that the anonymous method is not a full pink square but a white square surrounded by pink and in its definition there's a call to some CompilerServices classes but I don't know how to take advantage of this back in C#. I'm sure it's possible to get to know about the real nature of action. What am I missing?

Это было полезно?

Решение

For the sake of having an "accepted" answer on this question, I went as per the link given by Michael Kjörling in his first comment on my question.

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

Другие советы

Compiler generated methods will always have their names with angled brackets like below

Void <Main>b__0()

so why not just fetch the name and see if it has angled brackets in it.

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

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

or you can use much better pattern matching with regex

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top