This is going to be a quick and dirty blog post but hopefully, will take this giant stupidity out of me. Autofac, an awesome IoC container for .NET platform, has an out of the box generic service registration feature and I assume nearly all IoC containers have this today which makes me feel stupid because I have been knowing this for only a month or so I was doing something like below before.
private static void RegisterRepositories(ContainerBuilder builder) { Type baseEntityType = typeof(BaseEntity); Assembly assembly = baseEntityType.Assembly; IEnumerable<Type> entityTypes = assembly.GetTypes().Where( x => x.IsSubclassOf(baseEntityType)); foreach (Type type in entityTypes) { builder.RegisterType(typeof(EntityRepository<>) .MakeGenericType(type)) .As(typeof(IEntityRepository<>).MakeGenericType(type)) .InstancePerApiRequest(); } }
Then, Ben Foster pinged me on twitter:
@tourismgeek what, no For(type of(IFoo<>).Use(typeof(Foo<>)? Even Ninject supports that.
— Ben Foster (@benfosterdev) December 19, 2012
This tweet made me look for alternative approaches and I found out the Autofac's generic service registration feature. Here is how it looks like now:
private static void RegisterRepositories(ContainerBuilder builder) { builder.RegisterGeneric(typeof(EntityRepository<>)) .As(typeof(IEntityRepository<>)) .InstancePerApiRequest(); }
Way better! Autofac also respects generic type constraints. Here is a quote from the Autofac documentation:
Autofac respects generic type constraints. If a constraint on the implementation type makes it unable to provide a service the implementation type will be ignored.
If you didn't know this feature before, you do know it now Enjoy it!