Autofac 2 Sketch

Revision: 398
Author: nicholas.blumhardt
Date: 8:06:55 AM, Monday, 21 July 2008
Message:
Added 2.0-experimental branch for exploration of internal refactorings.

Yes, work on Autofac 2 began a year and a half ago! While work all but stopped while I did other things in Redmond, I’m pleased to say that a beta is finally in sight.

You might be curious just how close is ‘close’: there are six items in the issue tracker that I think need to be addressed:

  • 98 Support named registrations for open generics

  • 140 Cache constructor bindings in ReflectionActivator

  • 150 Human-readable display strings and [DebuggerDisplay]

  • 154 Update ConfigurationSettingsReader (XML Config Support)

  • 155 Update contrib and examples to 2.1

  • 160 Scan assemblies for modules

Most of these are pretty unexciting - minor features, niceties and dependent project updates.

Issue 98, however, has been in the system a while. One of the core improvements in Autofac 2 makes it easier and much more efficient to add support for dynamically-generated component registrations.

As an example, if IFoo is registered, Autofac provides or can be extended to provide:

  • Owned for explicit ownership/Iifetime control

  • Func for dynamically creating IFoo components

  • Lazy and Lazy<IFoo, IFooMetadata> for lazy instantiation

These can even be composed automatically to give Func<Owned> and so-on.

Under the hood, each extension is a handler that can look at a requested Service, query other available services, and generate a component on-the-fly that is able to fulfill the request.

The same underlying mechanism supports open generic types.

builder.RegisterGeneric(typeof(Bar<>)).As(typeof(IBar<>));

var container = builder.Build();

container.Resolve<IBar<int>>();

The handler checks to see if the requested Service is a closed instance of the open generic service type it is watching for (IBar<>). If it is, the handler creates a regular component by closing the generic component type (Bar<> becomes Bar), and from that point on the container will used the closed type to provide that particular closed service.

Now, all is well-and-good if the service is requested by type, as in Resolve().

Autofac uses NamedService and TypedService to represent services requested by name and by type respectively. When a component is resolved by name, as in Resolve("foo"), the dynamic registration handlers get an instance of NamedService { ServiceName = "foo" }.

NamedService, in Autofac 1.x and Autofac 2 today, doesn’t carry type information, just a string, so while Resolve("foo") succeeds, there's no way to automatically support Resolve<Func>("foo") - the handler can't see that the returned object should be of type Func.

And that is at the crux of issue 98. Adding type information to NamedService doesn’t seem like a big deal, but it does touch a lot of APIs and will break some existing apps in potentially confusing ways. It may be that issue 98 is put to the side this time around. Either way a decision has to be reached before Autofac 2 can be released as a beta.

Stay tuned, and have a safe holiday if you’re lucky enough to be taking one!