views:

57

answers:

3

Lets say I have a inheritance tree of interfaces:

IParent > IChild > IGrandChild

How would I:

  1. Find a class that implements IParent
  2. Determine the closest ancestor of the class that is also a child of IParent.

For example:

var myClass = FindImplementor<IParent>();
var myInterface = ClosestAncestor<IParent, myclass>();

I'm not looking to create functions that match the above signatures. That was just for clarification.

The descendants of IParent as well as the implementation class are in a dynamically loaded assembly. I'm not sure if that would make a difference or not.

+1  A: 

You can use the as keyword and check for null.

Example:

var someObject = GetMeSomething();  //returns some IParent/IChild/IGrandChild

if ((someObject as IParent) != null)
    if ((someObject as IChild) != null)
    {
        if ((someObject as IGrandChild) != null)
        {
            //you have an IGrandChild
        }
        else
        {
            //you have an IChild
        }
    }
    else
    {
        //you have an IParent
    }
}
//you have something other than your interface hierarchy

I'm not really liking the idea, actually, but it's what came to mind. There are a number of issues with trying to identify the chain. Multiple implementation chains come to mind.

Joseph
+1  A: 

To get "Implementors" of IParent

var classes = Assembly.GetTypes();
var parentImplementors = classes.Where(x => x.IsAssignableFrom(typeof(IParent)));

There is no simple and perfectly working way to get the "closest ancestors" of an interface.

Guillaume
A: 

I hope I understood the question correctly :)

ClosestAncestor

public Type ClosestAncestor<IParent, Class>()
{
    return ClosestAncestor<IParent>(typeof(Class));
}

public Type ClosestAncestor<IParent>(Type typeOfClass)
{
    var baseType = typeOfClass.BaseType;
    if(typeOfClass.GetInterfaces().Contains(typeof(IParent)) &&
        ! baseType.GetInterfaces().Contains(typeof(IParent)))
    {
        return typeOfClass;
    }

    return ClosestAncestor<IParent>(baseType);
}

As it can be seen, the code assumes Class implements IParent (otherwise - bug...).

Test sample:

public interface I {}
public class A {}
public class B : A, I {}
public class C : B {}

[Test]
public void ClosestAncestorTest()
{
    Type closestAncestor = ClosestAncestor<I,C>();
    Assert.AreEqual(typeof(B), closestAncestor);
}

FindImplementor

Loading first type that implements an interface:

public Type FindImplementor<T>()
{
    return AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(assembly => assembly.GetTypes())
        .FirstOrDefault(type => type.GetInterfaces().Contains(typeof(T)));
}

I assumed the assembly is loaded to the App Domain and the code searches all over the place for an implementer. If only single assembly is interesting, you can get only this assembly types (Like in Guillaume's answer)

Elisha
Your ClosestAncestor will fail when Type and BaseType both implement IParent interface.
Guillaume
@Guillaume, you're right, it's a bug :)
Elisha