项目

选项模式

微软引入了选项模式,用于配置框架服务所使用的设置组。该模式通过Microsoft.Extensions.Options NuGet包实现,因此不仅适用于基于ASP.NET Core的应用程序,也适用于任何类型的应用程序。

ABP遵循这一选项模式,并定义了选项类来配置框架和模块(相关功能的文档中会详细说明)。

由于微软官方文档已详细解释了该模式,此处不再赘述。然而,ABP添加了一些额外功能,本文将对此进行说明。

配置选项

通常,您可以在Startup类的ConfigureServices方法中配置选项。但由于ABP提供了模块化基础设施,您应在模块ConfigureServices方法中配置选项。例如:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.Configure<AbpAuditingOptions>(options =>
    {
        options.IsEnabled = false;
    });
}
  • AbpAuditingOptions是一个简单类,定义了如IsEnabled等属性。
  • AbpModule基类提供了Configure方法以简化代码。因此,您可以直接使用Configure<...>快捷方法,而无需写context.Services.Configure<...>

如果您正在开发可重用模块,可能需要定义一个选项类,以便开发人员配置您的模块。这种情况下,请定义一个简单的选项类,如下所示:

public class MyOptions
{
    public int Value1 { get; set; }
    public bool Value2 { get; set; }
}

然后开发人员可以像上述AbpAuditingOptions示例一样配置您的选项:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    Configure<MyOptions>(options =>
    {
        options.Value1 = 42;
        options.Value2 = true;
    });
}
  • 此示例中使用了快捷方法Configure<...>

获取选项值

当需要获取选项值时,请将IOptions<TOption>服务注入到您的类中,并使用其.Value属性。例如:

public class MyService : ITransientDependency
{
    private readonly MyOptions _options;
    
    public MyService(IOptions<MyOptions> options)
    {
        _options = options.Value; //注意这里使用了options.Value!
    }

    public void DoIt()
    {
        var v1 = _options.Value1;
        var v2 = _options.Value2;
    }
}

有关选项模式的完整细节,请阅读微软官方文档

预配置

选项模式的一个限制是,只有在依赖注入配置完成(即所有模块的ConfigureServices方法执行完毕)后,才能解析(注入)IOptions<MyOptions>并获取选项值。

如果您正在开发模块,可能需要允许开发人员在依赖注入注册阶段设置某些选项,并基于这些选项值配置其他服务或更改依赖注入注册代码。

针对这种情况,ABP为IServiceCollection引入了PreConfigure<TOptions>ExecutePreConfiguredActions<TOptions>扩展方法。该模式的工作原理如下。

在您的模块中定义一个预选项类。例如:

public class MyPreOptions
{
    public bool MyValue { get; set; }
}

然后,任何依赖您模块的模块类都可以在其PreConfigureServices方法中使用PreConfigure<TOptions>方法。例如:

public override void PreConfigureServices(ServiceConfigurationContext context)
{
    PreConfigure<MyPreOptions>(options =>
    {
        options.MyValue = true;
    });
}

多个模块可以预配置选项,并根据它们的依赖顺序覆盖选项值。

最后,您的模块可以在其ConfigureServices方法中执行ExecutePreConfiguredActions方法以获取配置的选项值。例如:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    var options = context.Services.ExecutePreConfiguredActions<MyPreOptions>();
    if (options.MyValue)
    {
        //...
    }
}
在本文档中