views:

492

answers:

2

I know some DI frameworks support this (e.g. Ninject), but I specifically want to know if it's possible with Autofac.

I want to be able to ask an Autofac container for a concrete class, and get back an instance with all appropriate constructor dependencies injected, without ever registering that concrete class. I.e., if I never bind it explicitly, then automatically bind the concrete class to itself, as if I had called builder.Register<MyClass>();

A good example of when this would be useful is ViewModels. In MVVM, the layering is such that only the View depends on the ViewModel, and that via loose typing, and you don't unit-test the View anyway. So there's no need to mock the ViewModel for tests -- and therefore there's no reason to have an interface for each ViewModel. So in this case, the usual DI pattern of "register this interface to resolve to this class" is unnecessary complexity. Explicit self-binding, like builder.Register<MyClass>();, also feels like an unnecessary step when dealing with something as straightforward as a concrete class.

I'm aware of the reflection-based registration example in the Autofac docs, but that's not to my taste either. I don't want the complexity (and slowness) of registering every possible class ahead of time; I want the framework to give me what I need when I need it. Convention over configuration, and all that.

Is there any way to configure Autofac so it can say "Oh, this is a concrete type, and nobody registered it yet, so I'll just act like it had been registered with default settings"?

+2  A: 

what about:

builder.RegisterTypesFromAssembly(Assembly.GetExecutingAssembly());

no reflection is done, as Peter Lillevold points out.

Carl Hörberg
Removed my previous comments because you were right (as you clarified in your edit): RegisterTypesFromAssembly doesn't do mass reflection as its name suggests. It's just one of a family of shorthand functions around RegisterTypesMatching, and does exactly what I'm looking for, but with much finer-grained control, which is pretty sweet. My apologies for misunderstanding your answer the first time around.
Joe White
+7  A: 

builder.RegisterTypesMatching(type => type.IsClass)

If you look at the source you will see that RegisterTypesMatching (and RegisterTypesFromAssembly) is NOT DOING ANY REFLECTION. All Autofac is doing in this case is registering a rule that accepts a type or not. In my example above I accept any type that is a class.

In the case of RegisterTypesFromAssembly, Autofac registers a rule that says "if the type you're trying to resolve have Assembly == the specified assembly, then I will give you an instance".

So:

  1. no type reflection is done at register time
  2. any type that matches the criteria will be resolved

Compared to register the concrete types directly, this will have a perf hit at resolve time since Autofac will have to figure out e.g. constructor requirements. That said, if you go with default instance scope, which is singleton, you take the hit only the first time you resolve that type. Next time it will use the already created singleton instance.

Update: in Autofac 2 there is a better way of making the container able to resolve anything. This involves the AnyConcreteTypeNotAlreadyRegistered registration source.

Peter Lillevold
Sweet -- sounds like exactly what I was looking for. Thanks!
Joe White