Autofac 之二 注册组件程序集扫描注入
author:尹明能 引入国外网站
Registration Concepts(注册概念)
You register components with Autofac by creating a ContainerBuilder
and informing (通知)the builder which components expose which services.
Components can be created via reflection (by registering a specific .NET type or open generic); by providing a ready-made instance (通过提供现成的实例)(an instance of an object you created); or via lambda expression (an anonymous function that executes to instantiate your object). ContainerBuilder
has a family of Register()
methods that allow you to set these up.
Each component exposes one or more services that are wired up using the As()
methods on ContainerBuilder
.
Assembly Scanning(程序集扫描)
Autofac can use conventions(约定) to find and register components in assemblies. You can scan and register individual (单个)types or you can scan specifically for Autofac modules.
Scanning for Types
Otherwise known as convention-driven registration or scanning, Autofac 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.
Autofac also supports assembly scanning for open generics using RegisterAssemblyOpenGenericTypes()
. This uses the same general (通用的)semantics(语义学) as RegisterAssemblyTypes()
:
Filtering Types(类型筛选)
RegisterAssemblyTypes()
and RegisterAssemblyOpenGenericTypes()
each accept a parameter array of one or more assemblies. By default, all concrete(具体的) classes in the assembly will be registered. This includes internal(内部的) and nested(嵌套的) private classes. You can filter the set of types to register using some provided LINQ-style predicates.
In 4.8.0 a PublicOnly()
extension was added to make data encapsulation(封装) easier. If you only want your public classes registered, use PublicOnly()
:
builder.RegisterAssemblyTypes(asm)
.PublicOnly();
To apply custom filtering to the types that are registered, use the Where()
predicate:
builder.RegisterAssemblyTypes(asm) .Where(t => t.Name.EndsWith("Repository"));
To exclude(排除) types from scanning, use the Except()
predicate:
builder.RegisterAssemblyTypes(asm)
.Except<MyUnwantedType>();
The Except()
predicate also allows you to customize the registration for the specific excluded type:
builder.RegisterAssemblyTypes(asm) .PublicOnly() .Where(t => t.Name.EndsWith("Repository")) .Except<MyUnwantedRepository>();
Specifying Services(指定服务)
The registration syntaxes for RegisterAssemblyTypes()
and RegisterAssemblyOpenGenericTypes()
are a subset (子集)of the registration syntax for single types(单个类型), so methods like As()
all work with assemblies as well(也):
builder.RegisterAssemblyTypes(asm) .Where(t => t.Name.EndsWith("Repository")) .As<IRepository>();
Additional(额外的) overloads(重载) to As() and Named() accept lambda expressions that determine (决定), for a type, which services it will provide:
builder.RegisterAssemblyTypes(asm) .As(t => t.GetInterfaces()[0]);
common conventions:
Method |
Description |
Example |
---|---|---|
|
Register the type as providing all of its public interfaces as services (excluding |
builder.RegisterAssemblyTypes(asm)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
|
|
Register types that are assignable to a closed instance of the open generic type. |
builder.RegisterAssemblyTypes(asm)
.AsClosedTypesOf(typeof(IRepository<>));
|
|
The default: register types as themselves - useful when also overriding the default with another service specification. |
builder.RegisterAssemblyTypes(asm)
.AsImplementedInterfaces()
.AsSelf();
|
Scanning for Modules
Module scanning is performed with the RegisterAssemblyModules()
registration method, which does exactly what its name suggests. It scans through the provided assemblies for Autofac modules, creates instances of the modules, and then registers them with the current container builder.
For example, say the two simple module classes below live in the same assembly and each register a single component:
public class AModule : Module { protected override void Load(ContainerBuilder builder) { builder.Register(c => new AComponent()).As<AComponent>(); } } public class BModule : Module { protected override void Load(ContainerBuilder builder) { builder.Register(c => new BComponent()).As<BComponent>(); } }
The overload of RegisterAssemblyModules()
that does not accept a type parameter will register all classes implementing IModule
found in the provided list of assemblies. In the example below both modules get registered:
var assembly = typeof(AComponent).Assembly; var builder = new ContainerBuilder(); // Registers both modules builder.RegisterAssemblyModules(assembly);
The overload of RegisterAssemblyModules()
with the generic type parameter allows you to specify a base type that the modules must derive from. In the example below only one module is registered because the scanning is restricted:
var assembly = typeof(AComponent).Assembly; var builder = new ContainerBuilder(); // Registers AModule but not BModule builder.RegisterAssemblyModules(typeof(AModule), assembly);
posted on 2022-05-30 17:40 topguntopgun 阅读(184) 评论(0) 编辑 收藏 举报