猿教程 Logo

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()添加到一起。

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


扫描模块

使用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();

// Registers both modules
builder.RegisterAssemblyModules(assembly);

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

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

// Registers AModule but not BModule
builder.RegisterAssemblyModules<AModule>(assembly);

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

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

// Registers AModule but not 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中,立即使它们可用于模块扫描。


版权声明:本站所有教程均为本站原创或翻译,转载请注明出处,请尊重他人劳动果实。请记住本站地址:www.yuanjiaocheng.net (猿教程) 作者:卿文刚
本文标题: C#环境
本文地址:http://www.yuanjiaocheng.net/Autofac/scanning.html