Rob Stevenson-Leggett
Rob Stevenson-Leggett

Reputation: 35679

C#: Test if an object implements any of a list of interfaces?

I want to test if a type implements one of a set of interfaces.

    ViewData["IsInTheSet"] =
            model.ImplementsAny<IInterface1, IInterface2, IInterface3, IInterface4>();

I have written the following extension methods to handle this.

Is there a more extensible way to write the following code? I would prefer not to have to write a new method while still leveraging generics.

    public static bool Implements<T>(this object obj)
    {
        Check.Argument.IsNotNull(obj, "obj");

        return (obj is T);
    }

    public static bool ImplementsAny<T>(this object obj)
    {
        return obj.Implements<T>();
    }

    public static bool ImplementsAny<T,V>(this object obj)
    {
        if (Implements<T>(obj))
            return true;
        if (Implements<V>(obj))
            return true;
        return false;
    }

    public static bool ImplementsAny<T,V,W>(this object obj)
    {
        if (Implements<T>(obj))
            return true;
        if (Implements<V>(obj))
            return true;
        if (Implements<W>(obj))
            return true;
        return false;
    }

    public static bool ImplementsAny<T, V, W, X>(this object obj)
    {
        if (Implements<T>(obj))
            return true;
        if (Implements<V>(obj))
            return true;
        if (Implements<W>(obj))
            return true;
        if (Implements<X>(obj))
            return true;
        return false;
    }

Upvotes: 4

Views: 522

Answers (2)

M.Babcock
M.Babcock

Reputation: 18965

The way I check if an interface has been implemented is:

public static bool IsImplementationOf(this Type checkMe, Type forMe)
{
    if (forMe.IsGenericTypeDefinition)
        return checkMe.GetInterfaces().Select(i =>
        {
            if (i.IsGenericType)
                return i.GetGenericTypeDefinition();

            return i;
        }).Any(i => i == forMe);

    return forMe.IsAssignableFrom(checkMe);
}

This could be easily extended to:

public static bool IsImplementationOf(this Type checkMe, params Type[] forUs)
{
    return forUs.Any(forMe =>
    {
        if (forMe.IsGenericTypeDefinition)
            return checkMe.GetInterfaces().Select(i =>
            {
                if (i.IsGenericType)
                    return i.GetGenericTypeDefinition();

                return i;
            }).Any(i => i == forMe);

        return forMe.IsAssignableFrom(checkMe);
    });
}

Or better yet:

public static bool IsImplementationOf(this Type checkMe, params Type[] forUs)
{
    return forUs.Any(forMe => checkMe.IsImplementationOf(forMe));
}

Warning: Untested

Then just do a typeof on your type parameters before passing them to this.

Upvotes: 1

Justin Niessner
Justin Niessner

Reputation: 245419

Why not use something like the following:

public static bool ImplementsAny(this object obj, params Type[] types)
{
    foreach(var type in types)
    {
        if(type.IsAssignableFrom(obj.GetType())
            return true;
    }

    return false;
}

Then you can call it like:

model.ImplementsAny(typeof(IInterface1),
                    typeof(IInterface2),
                    typeof(IInterface3),
                    typeof(IInterface4));

Upvotes: 5

Related Questions