views:

131

answers:

4

I'm not sure of the exact terminology here. Basically, if I have a model like:

class Student : IDoSchool {}
class Freshman : Student {}
interface IDoSchool {}

What code would tell me that Freshman doesn't directly implement any interfaces and Student directly implements IDoSchool?

In other words (disregarding bad terminology) I want something like this:

typeof(Freshman).GetInterfaces(BindingFlags.DeclaredOnly); // nothing
typeof(Student).GetInterfaces(BindingFlags.DeclaredOnly); // IDoSchool

Thoughts?

A: 

Just an idea...

You can get interfaces of the class, and interfaces of the base class. Then get the difference.

EDIT:

I've checked the idea, works:

public static Type[] GetDirectInterfaces(Type type)
{
    if (type.BaseType == null)
        return type.GetInterfaces();
    Type[] BaseInterfaces = type.BaseType.GetInterfaces();
    Type[] ThisInferfaces = type.GetInterfaces();
    return ThisInferfaces.Except(BaseInterfaces).ToArray();
}

If the amount of interfaces is huge and the execution time is crucial, you can create a separate static class with dictionary to cache results.

modosansreves
If the hierarchy is deep I can see this being a pain. I'd have to get the whole graph, find the highest point, walk down till I see an interface, and ignore that interface from that point on. I was hoping there was a more "built-in" way to do this. If I'm off on the process can you give an example?
TheDeeno
This won't work since the child class can also explicitly implement the interface
Coincoin
We can see if an member explicitly implements an interface. So if we assume explicit interfaces will be ignored would it be possible?
TheDeeno
A: 

Sorry for posting this as an answer, it's actually more a thought and a suggestion, but it wouldn't fit into a comment...

What if you have the following situation:

interface IA{
    void foo();
}
class CA : IA{
    public void foo(){
        Console.Writeline("Class A");
    }
}
class CB : CA, IA{
    public new void foo(){
        Console.Writeline("Class B");
    }
}

I guess CB should return IA among the 'directly implemented interfaces', but if you compare CB against CA you will see that they implement the same interfaces, so a find-the-differences approach would not work.
Before getting crazy looking for a solution, have you tried looking at the MSIL or at the code decompiled from Reflector to see if this is possible at all?

Paolo Tedesco
+1  A: 

I suspect the semantic of an interface is not in alignment with what you are trying to do.

An interface simply says that a class has to implemnt a list of members. The class inherits the interface but it is still the responsibilityy of the children class to implement the interface it inherited from the parent. Most of the case, the parent already provide an implementation, so we tend to perceive interface implementation as the same as inheritance but they are in fact totally different concepts.

In your case, the best you can do is retreive the interface mapping using GetInterfaceMap() and make sure all implementation of every memeber of the interface come from the parent, not from the child. This is the best you can do, but still, it won't exactly do what you are trying to do.

Also, is it possible in your case to use totally abstract classes instead of interfaces? You can't do multiple inheritance but maybe all your rules imply a very linear inheritance?

Coincoin
I'm working on the .net validation framework. One of ways rules can be configured is via attributing. Up until now there was support for being able to attribute interfaces and have those rules applied to types that implement that interface. I didn't write the original support, and I suspect (cont)
TheDeeno
it might not work as expected. I wanted to rewrite this feature so it was clearer which scenarios are supported. I've walking the type hierarchy fine except for this issue. For the above model and attribute on IDoSchool will be found twice since GetInterfaces() will return IDoSchool (cont)
TheDeeno
for both types. Thus we end up with two rules applied to Freshman when only one should be applied. If there isn't possible I'm not apposed to dropping the support for attributing interfaces (not sure it makes much sense anyways) I just didn't want to take a step backwards in functionality.
TheDeeno
That's strange because on my tests, GetInterfaces only returned one interface, even with orsogufo code. From what I understand, your interface will have an attribute and you want the parent class to inherit the attr but not the child class? If so, I'm affraid there is no out of the box solution.
Coincoin
Implementing an interface is a contract between to classes that want to share the same language, not an inheritance relation between the implementer and the interface. An interface should not be regarded as a totally abstract class, they are not the same. I updated the answer to cover a new solution
Coincoin
A: 
 typeof("the object").GetInterfaces().Count==0
Avram