Tigraine

Daniel Hoelbling-Inzko talks about programming

Juggling generics

Posted by Daniel Hölbling on June 10, 2009

I’ve spent the last two days working on true generic registrations inside Pandora to enable scenarios like this:

[Fact]
public void CanResolveRealGenericAsSubdependency()
{
    store.Register(p =>
                       {
                           p.Service<IService>()
                               .Implementor<ClassDependingOnGenericClass>();
                           p.Generic(typeof (GenericClass<>))
                               .Implementor(typeof (GenericClass<>))
                               .ForAllTypes();
                       });
    Assert.DoesNotThrow(() => container.Resolve<IService>());
}

Well, if you look at the last changeset, I apparently succeeded for the above example, but decided to revert the changes and start over fresh. Generics are a difficult topic to tackle, and the current implementation feels too much like a hack to me.

But there are some things this failed experiment has taught me:

First: Generic types are just Types. And there are two subclasses of them:

  1. GenericTypeDefinition – This one represents the generic with no supplied type argument. Eg: typeof(Service<>)  Cannot be activated.
  2. GenericType – Represents the final type that can be treated like a normal type. Eg: typeof(Service<string>)

So, how do you tell those 3 apart (the third being a normal non-generic)?
Simple: Both generic types have the IsGenericType property set to true and GenericTypeDefinition also has IsGenericTypeDefinition set to true.

If you are faced with a GenericType, you can always extract the GenericTypeDefinition by calling GetGenericTypeDefinition() (very useful if you try to compare types in some scenarios).


The inverse can also be done (creating a GenericType from a definition) by calling MakeGenericType():

var type = typeof (string);
Type genericType = typeof (GenericClass<>).MakeGenericType(type);

And, in case you want to know what the argument type (T part) of a generic type is you can use the GetGenericArguments() method to find out:

[Fact]
public void ExtractGenericArgumentType()
{
    var type = typeof (SuperGeneric<string, int, long, float>);
    Type[] arguments = type.GetGenericArguments();
    foreach (var argument in arguments)
    {
        Console.WriteLine(argument.Name);
    }
}

The above produces the following:

String
Int32


Int64


Single

Ps: Try this stuff out for yourself! Reflection is real fun and surely helped me understand some things better. Don’t let yourself be thrown off by comments like “Reflection is too slow, never use it” etc.. Reflection and dynamic activation can make your life much easier if you know how to use it!

Filed under net, programmierung
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more