Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the immediate implemented interfaces on a type

Tags:

c#

reflection

When calling typeof(Bar).GetInterfaces() on the following scenario the method returns IFoo and IBar.

interface IFoo {}
interface IBar : IFoo {}
class Bar : IBar {}

Is there a way that I can find only the immediate interface (IBar) on Bar?

like image 318
sduplooy Avatar asked Jan 13 '10 08:01

sduplooy


2 Answers

No, there's no such thing as the "immediate" interface in the compiled code. Your class is effectively compiled as:

class Bar : IBar, IFoo { }

and you can't distinguish between the two. The only thing you could do is to check all of them and see whether two or more of the interfaces inherit from each other or not (and even in that case, you can't really check whether the author of the class has explicitly mentioned the base interface in code or not):

static IEnumerable<Type> GetImmediateInterfaces(Type type)
{
    var interfaces = type.GetInterfaces();
    var result = new HashSet<Type>(interfaces);
    foreach (Type i in interfaces)
        result.ExceptWith(i.GetInterfaces());
    return result;
}
like image 64
mmx Avatar answered Sep 18 '22 11:09

mmx


public interface IRoo { }
public interface ISoo : IRoo { }
public interface IMoo : ISoo { }
public interface IGoo : IMoo { }
public interface IFoo : IGoo { }
public interface IBar : IFoo { }
public class Bar : IBar { }

private void button1_Click(object sender, EventArgs e) {
    Type[] interfaces = typeof(Bar).GetInterfaces();    
    Type immediateInterface = GetPrimaryInterface(interfaces);
    // IBar
}

public Type GetPrimaryInterface(Type[] interfaces)
{
    if (interfaces.Length == 0) return null;
    if (interfaces.Length == 1) return interfaces[0];

    Dictionary<Type, int> typeScores = new Dictionary<Type, int>();
    foreach (Type t in interfaces)
        typeScores.Add(t, 0);

    foreach (Type t in interfaces)
        foreach (Type t1 in interfaces)
            if (t.IsAssignableFrom(t1))
                typeScores[t1]++;

    Type winner = null;
    int bestScore = -1;
    foreach (KeyValuePair<Type, int> pair in typeScores) {
        if (pair.Value > bestScore) {
            bestScore = pair.Value;
            winner = pair.Key;
        }
    }
    return winner;
}
like image 43
serhio Avatar answered Sep 18 '22 11:09

serhio