Autofac官方文档(六)【注册组件之程序集扫描】

Autofac可以使用约定来查找和注册程序集中的组件。 您可以扫描并注册各种类型,也可以专门扫描Autofac模块。

扫描类型

否则称为惯例驱动的注册或扫描,Autofac可以根据用户指定的规则从程序集中注册一组类型:

var dataAccess = Assembly.GetExecutingAssembly();

builder.RegisterAssemblyTypes(dataAccess)
       .Where(t => t.Name.EndsWith("Repository"))
       .AsImplementedInterfaces();

每个RegisterAssemblyTypes()调用将仅应用一组规则 - 如果要注册多个不同组的组件,则需要多次调用RegisterAssemblyTypes()

过滤类型

RegisterAssemblyTypes()接受一个或多个程序集的参数数组。 默认情况下,程序集中的所有公共具体类都将被注册。 您可以使用一些提供的LINQ样式谓词来过滤要注册的类型集。

要筛选已注册的类型,请使用Where()谓词:

builder.RegisterAssemblyTypes(asm)
       .Where(t => t.Name.EndsWith("Repository"));

要从扫描中排除类型,请使用Except()谓词:

builder.RegisterAssemblyTypes(asm)
       .Except<MyUnwantedType>();

Except()谓词还允许您为特定的排除类型自定义注册:

builder.RegisterAssemblyTypes(asm)
       .Except<MyCustomisedType>(ct =>
          ct.As<ISpecial>().SingleInstance());

可以使用多个过滤器,在这种情况下,它们将被应用逻辑AND。

指定服务

RegisterAssemblyTypes()的注册语法是单一类型的注册语法的超集,所以像As()这样的方法也可以使用程序集:

builder.RegisterAssemblyTypes(asm)
       .Where(t => t.Name.EndsWith("Repository"))
       .As<IRepository>();

As()Named()的可选重载接受lambda表达式,这些表达式决定了一个类型,它将提供哪些服务:

builder.RegisterAssemblyTypes(asm)
       .As(t => t.GetInterfaces()[0]);

与正常的组件注册一样,多个对As()的调用被加在一起。

增加了一些额外的注册方法,以便更容易地建立通用约定:

MethodDescriptionExample
AsImplementedInterfaces()将类型注册为将其所有公共接口提供为服务(不包括IDisposable)builder.RegisterAssemblyTypes(asm).Where(t => t.Name.EndsWith(“Repository”)).AsImplementedInterfaces();
AsClosedTypesOf(open)注册可分配给已打开泛型类型的已关闭实例的类型。.builder.RegisterAssemblyTypes(asm).AsClosedTypesOf(typeof(IRepository<>));
AsSelf()默认值:注册类型为自己的 - 当用另一个服务规范覆盖默认值时也很有用.builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().AsSelf();

扫描模块

模块扫描是通过RegisterAssemblyModules()注册方法来完成的,而注册方法正是其名字所暗示的。 它扫描所提供的Autofac模块的程序集,创建模块的实例,然后将其注册到当前的容器生成器。

例如,假设下面的两个简单模块类存在同一个程序集中,并且每个注册一个组件:

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>();
  }
}

不接受类型参数的RegisterAssemblyModules()的重载将注册在提供的程序集列表中找到的实现IModule的所有类。 在下面的例子中,两个模块都被注册了:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

//注册这两个模块
builder.RegisterAssemblyModules(assembly);

RegisterAssemblyModules()与泛型类型参数的重载允许您指定(模块必须从中派生的)基本类型。 在下面的例子中,只有一个模块被注册,因为扫描受到限制:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

//注册模块但不包含BModule
builder.RegisterAssemblyModules<AModule>(assembly);

使用Type对象参数的RegisterAssemblyModules()的重载与通用类型参数重载类似,但允许您指定可能在运行时确定的类型。 在下面的例子中,只有一个模块被注册,因为扫描受到限制:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

// 注册模块但不包含BModule
builder.RegisterAssemblyModules(typeof(AModule), assembly);

IIS托管的Web应用程序

在IIS应用程序中使用程序集扫描时,根据程序集位置的不同,可能会遇到一些麻烦。 (这是我们的常见问题之一)

在IIS中托管应用程序时,应用程序首次启动时,所有程序集都加载到AppDomain中,但当AppDomain被IIS回收时,程序集仅在需要时加载。

为避免此问题,请使用System.Web.Compilation.BuildManager上的GetReferencedAssemblies()方法来获取引用程序集的列表:

var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();

这将强制引用的程序集立即加载到AppDomain中,使其可用于模块扫描.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值