|
Scanning
Autofac can use conventions to find and register components in assemblies.
Autofac2 Component DiscoveryOtherwise known as convention-driven registration or scanning, Autofac 2 can register a set of types from an assembly according to user-specified rules: var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();Each RegisterAssemblyTypes() call will apply one set of rules only - multiple invocations of RegisterAssemblyTypes() are necessary if there are multiple different sets of components to register. Selecting TypesRegisterAssemblyTypes() accepts an array of assemblies. By default, all public, concrete classes in the assembly will be registered. To filter the types that are registered, use Where(), as in: Where(t => t.Name.EndsWith("Repository"))To exclude types from scanning, use Except(): Except<MyUnwantedType>() Or, customise the registration for the excluded type with: Except<MyCustomisedType>(ct =>
ct.As<ISpecial>().SingleInstance())Multiple filters can be used, in which case they will be applied with logical AND. Specifying ServicesThe registration syntax for RegisterAssemblyTypes() is a superset of the registration syntax for single types, so methods like As() all work with assemblies as well, e.g.: As<IRepository>() Additional overloads to As() and Named() accept lambda expressions that determine, for a type, which services it will provide: As(t => t.GetInterfaces()[0]) As with normal component registrations, multiple calls to As() are added together. Convenience MethodsA number of convenience methods make it easier to build up common conventions.
| |
I like selecting my types via "opt-in" by putting a custom attribute on the class:
[AttributeUsage(AttributeTargets.Class)] public class RegisterServiceAttribute : Attribute {}Then select the types like this:
builder.RegisterAssemblyTypes(assemblies) .Where(t => t.GetCustomAttributes(typeof (RegisterServiceAttribute), false).Any()) .AsSelf() .AsImplementedInterfaces();A common one is AsDefaultInterface?. Instead of registering all the interfaces defined by the type I want to register IProductRepository for ProductRepository?. I added an extension method to do this. Have a look at https://gist.github.com/799706
While doing that I noticed that AsImplementedInterfaces? has a different behavior if it's applied to a type or assembly. For the latter it excludes IDisposable. It might be worth unifying this behavior (IMO IDisposable should be excluded in both cases).
Miguel, thanks for noticing the IDisposable issue, I'll add a note to the tracker.