Finding a common namespace root for an assembly

“What’s the difference between a namespace and an assembly?”

It’s a very standard interview question and I’m sure we can all answer that one easily.  And so we all know that it’s possible for an assembly to contain types from a variety of namespaces and that these namespaces may or may not have anything in common with each other.

But in the real world, types within an assembly typically do have something in common with each other.  And usually there is a common portion of the namespace names.  And in case you want to work out what that common portion is, here is some code:

public static class AssemblyHelper
{
    public static string DeduceRootNamespaceParts(Assembly assembly)
    {
        var splitNamespaces = assembly.GetTypes()
            .Where(type => type.IsPublic)
            .Select(type => type.Namespace.Split('.'))
            .ToArray();

        var largestCommonality = 0;

        do
        {
            if(largestCommonality >= splitNamespaces[0].Length)
                break;

            var valueToTest = splitNamespaces[0][largestCommonality];
            var commonality = largestCommonality;
            var areAllSame = splitNamespaces.All(strings => strings.Length > commonality && strings[commonality] == valueToTest);
            if(!areAllSame)
                break;
            largestCommonality++;
        } while (true);

        return String.Join(".", splitNamespaces[0].Take(largestCommonality).ToArray());
    }
}

I suspect that this code is O(n) complexity with regard to the number of types contained in the assembly, but I haven’t thought about it terribly deeply.

April 28 2010

Reflection on Generic Types (part 2)

Some time ago I posted a question about reflection on generics.  This remained unanswered until Anthony recently posted the solution in a comment.  To reiterate what was said in there:

The Question

I have a generic interface ICustomDataMapper<T>.  I want to know, programatically, if a Type t which has been passed to my method implements this interface, or at least a closed version thereof.  The best I could come up with was:

bool DoesImplement = false;
foreach (Type intface in t.GetInterfaces())
{
     if (intface.IsGenericType &&
        intface.GetGenericTypeDefinition().Name.StartsWith
              
("ICustomDataMapper"))
     DoesImplement =
true;
}

This is a bit rubbish.  Can anyone show me a better way?

Anthony's Solution

Anthony suggested instantiating a concrete version of the generic type to relfect over it.  This doesn't work too well with interfaces, but a simple modification gets it to work as follows:

bool DoesImplement = false;
Type GenericBase = typeof(ICustomDataMapper<string>).GetGenericTypeDefinition();
foreach (Type intface in t.GetInterfaces())
{
     if (intface.IsGenericType &&
        intface.GetGenericTypeDefinition() == GenericBase)

     DoesImplement =
true;
}

Yet Another Way

This prompted some further investigation and I found out that there are two other ways to access the generic type:

Type GenericBase = Type.GetType("MyProject.DataMapping.ICustomDataMapper`1");

Although it works, this is back to being a bit rubbish because the type name is coded in a string so there is no compile-time checking.  Also we need to use the fully qualified type name.  However, the following also works and gets around these problems:

Type GenericBase = typeof( ICustomDataMapper<> );

I think that this has to be the neatest solution. 

An Unrelated Aside

As per Anthony's comment, the number after the backtick ( ` ) relates to the number of generic type parameters on the definition.  This means that a generic type with two parameters is completely unrelated to one with only one, even if they share the same name.  Or to put it another way, the following two definitions can be in the same namespace:

public interface IGeneric<T>
{
    T DoSomething(T t);
}

public interface IGeneric<K, V>
{
    K DoSomethingElse(V v);
}

A type can then implement both of these interfaces, as in:

public class Concrete: IGeneric<Concrete>, IGeneric<string, Concrete>

November 2 2006

Reflection on Generic Types

I really love Generics in .Net 2.0 - I think they're great.  They remove a lot of that nasty casting to objects which we had to do in .Net 1.x and they generally improve type-safety.  However, I recently hit a problem when trying to do some reflection against generic types.

I have a generic interface ICustomDataMapper<T>.  I want to know, programatically, if a Type t which has been passed to my method implements this interface, or at least a closed version thereof.  The best I could come up with was:

bool DoesImplement = false;
foreach (Type intface in t.GetInterfaces())
{
     if (intface.IsGenericType &&
        intface.GetGenericTypeDefinition().Name.StartsWith
              
("ICustomDataMapper"))
     DoesImplement =
true;
}

This is a bit rubbish.  Can anyone show me a better way?

August 7 2006
Older Posts