Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type.GetInterfaces() for declared interfaces only

Tags:

c#

reflection

First of all, there are many questions just like this, and perhaps some OPs were even asking this exact same question. The problem is that no answer to those questions (accepted or not) actually answer this question, at least none that I can find.

How can I determine the interfaces a class declares directly, and not those inherited either by parents nor by the interfaces declared?

e.g.

interface I {}
interface W : I {}
class C : W {}
class D : C, I {}
class E : D {}

Results:

  1. C declares W
  2. D declares I
  3. E declares none

An acceptable solution could require the interfaces to have at least one method.

If you think it truly is impossible, be careful not to make this mistake, which actually can be done.

The InterfaceMap handles many cases, but not all (I give an example below not solvable by InterfaceMap). One idea I had, but don't know how to implement it, is to decompile the bytecode of the class and see what is declared, as tools such as ILSpy correctly identify every case! If you like this idea, please give me a link to more info in this area.

I expect some of you will advise me to clean up my design. If this is not your argument, the rest of the post is not relevant for you.

Part of my project's purpose is in tracing potential code paths of given Types (at runtime). In order to determine programmatically which method will be called on a target type, without actually invoking the method nor creating an instance of the target type, knowing the declared interfaces of a target type is requisite to deterministically solve this. 'Nay' you say? Consider:

interface I { int Foo(); }
class C : I { public int Foo() { return 1; } }
class D : C { public new int Foo() { return 2; } }
class E : D, I { }

C p = new E();
Assert.AreEqual(1 or 2, (p as I).Foo())

The correct answer is 2, but if you change the declaration of E to not include I directly, the answer is 1. Now sure this is edge case, but it is the correct answer too. My engine is therefore is not fully compatible with potential user code. Telling the users to clean their code in order to use my tool is not acceptable. (Note there are dozens more interesting rules with casting to an interface, but I'll not discuss them here).

like image 441
payo Avatar asked Mar 20 '12 19:03

payo


People also ask

How to get interface type c#?

GetInterface(String) Method This method is used to search for the interface with the specified name. Syntax: public Type GetInterface (string name); Here, it takes the string containing the name of the interface to get. For generic interfaces, this is the mangled name.

Is interface a type in C#?

Interfaces define properties, methods, and events, which are the members of the interface. Interfaces contain only the declaration of the members. Some of the interface types in C# include.


1 Answers

To get only the declared interfaces for a given type you could use GetInterfaces on the given type, then if it has a BaseType you could use the Except enumerator to exclude the base type's interfaces...

It's untested, but perhaps something like this extension method...

public static IEnumerable<Type> GetDeclaredInterfaces(this Type t)
{
    var allInterfaces = t.GetInterfaces();
    var baseInterfaces = Enumerable.Empty<Type>();
    if (t.BaseType != null)
    {
        baseInterfaces = t.BaseType.GetInterfaces();
    }
    return allInterfaces.Except(baseInterfaces);
}
like image 145
Reddog Avatar answered Oct 02 '22 02:10

Reddog