Проверка того, является ли определенный тип делегатом действия

Я пытаюсь проверить, является ли данный тип-делегат action, независимо от количества параметров.

следующий код-единственный способ, которым я знаю, как это сделать.

    public static bool IsActionDelegate( this Type source )
    {
        return source == typeof( Action ) ||
               source.IsOfGenericType( typeof( Action<> ) ) ||
               source.IsOfGenericType( typeof( Action<,> ) ) ||
               ....
               source.IsOfGenericType( typeof( Action<,,,,,,,,,,,,,,,> ) );
    }

IsOfGenericType() - это еще один мой метод расширения, который делает то, что он говорит, он проверяет, является ли тип заданным общим типом.

другие предложения?

4 ответов


если вы сразу после делегатов, которые имеют тип возврата void, вы можете сделать следующее:

public static bool IsActionDelegate(Type sourceType)
{
    if(sourceType.IsSubclassOf(typeof(MulticastDelegate)) && 
       sourceType.GetMethod("Invoke").ReturnType == typeof(void))
        return true;
    return false;
}

это не будет различать Action и MethodInvoker (или другие пустые делегаты, если на то пошло). Как и другие ответы, вы можете изучить имя типа, но это пахнет ;-) Было бы полезно, если бы вы могли уточнить, по какой причине вы хотите идентифицировать Action делегатов, чтобы увидеть, какой подход будет работать лучше.


    static Type[] _actionTypes = new[]{
        typeof(Action),
        typeof(Action<>),
        typeof(Action<,>),
        typeof(Action<,,>),
        typeof(Action<,,,>),
        typeof(Action<,,,,>),
        typeof(Action<,,,,,>),
        typeof(Action<,,,,,,>),
        typeof(Action<,,,,,,,>),
        typeof(Action<,,,,,,,,>),
        typeof(Action<,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,,,,,>),
        typeof(Action<,,,,,,,,,,,,,,,>)
    };
    private static bool IsAction(Delegate d)
    {
        return d != null && Array.IndexOf(_actionTypes, d.GetType()) != -1;
    }

Это, кажется, работает:

    private static bool IsActionDelegate(this Type source)
    {
        var type = source.Name;
        return source.Name.StartsWith("System.Action");
    }

пример:

public static class Test
{
    public static bool IsActionDelegate(this Type source)
    {
        var type = source.Name;
        return source.Name.StartsWith("Action");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Action<string> one = s => { return; };
        Action<int, string> two = (i, s) => { return; };
        Func<int, string> function = (i) => { return null; };

        var single = one.GetType().IsActionDelegate();
        var dueces = two.GetType().IsActionDelegate();
        var func = function.GetType().IsActionDelegate();
    }
}

Single и dueces истинны. func является ложным


Это разные типы, не имеющие ничего общего, кроме своего имени. Единственный полуразумный ярлык, который я могу придумать:

public static bool IsActionDelegate( this Type source )
{
    return source.FullName.StartsWith("System.Action");
}

конечно не безопасно, но кто декларирует собственные типы в пространстве имен System заслуживает боли и страданий.