探索ABP基礎架構-下

張飛洪[廈門]發表於2022-05-17

配置應用程式

ASP.NET Core 的配置系統提供了一個基於鍵值對的配置方法。它是一個可擴充套件的系統,可以從各種資源中讀取鍵值對,例如 JSON 設定檔案、環境變數、命令列引數等等。

設定配置值

預設使用appsettings.json檔案是配置的最簡單方法。假設我們正在構建一個使用 Azure 傳送 SMS 的服務,並且我們需要以下配置值:

  • Sender: 發件人號碼
  • ConnectionString: 你的 Azure 資源的連線字串

我們可以在appsettings.json檔案的配置部分定義這些:

{
  ...
  "AzureSmsService": {
    "Sender": "+901112223344",
    "ConnectionString": "..."
  }
}

這裡的鍵名是完全任意的,只要您在程式碼中使用相同的鍵,您就可以輕鬆地讀取它們的值。

讀取配置值

您可以在需要讀取配置值的地方注入IConfiguration以使用該服務。例如,我們可以在 AzureSmsService中獲取Azure 配置值用於傳送 SMS:

using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
namespace SmsSending
{
    public class AzureSmsService : ISmsService, ITransientDependency
    {
        private readonly IConfiguration _configuration;
        public AzureSmsService(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        
        public async Task SendAsync(string phoneNumber, string message)
        {
            string sender = _configuration["AzureSmsService:Sender"];
            string ConnectionString = _configuration["AzureSmsService:ConnectionString"];
            //TODO: Use Azure to send the SMS message
        }
    }
}

IConfiguration服務也可用於ConfigureServices中:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    IConfiguration configuration = context.Services.GetConfiguration();
    string sender = configuration["AzureSmsService:Sender"];
}

這裡,我們可以在服務注入之前訪問配置值。

以上的配置方式固然方便,但是,如果您正在構建一個可重用的庫,則選項模式可能是更好的方法,因為它是型別安全

實現選項模式

為了使用選項模式,我們使用一個普通的類(有時稱為POCOPlain Old C# Object),我們從如何定義、配置和使用配置開始。

定義選項類

選項類是一個簡單的類。我們為 Azure SMS 服務定義一個選項類,如以下程式碼塊所示:

public class AzureSmsServiceOptions
{
    public string Sender { get; set; }
    public string ConnectionString { get; set; }
}

將字尾Options新增到選項類是一種約定。

配置選項

您可以在模組的ConfigureServices方法中配置,可以使用IServiceCollection.Configure的擴充套件方法為任何選項類設定值。看下下面的程式碼塊是如何配置的:

[DependsOn(typeof(SmsSendingModule))]
public class MyStartupModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.Configure<AzureSmsServiceOptions>(options =>
        {
            options.Sender = "+901112223344";
            options.ConnectionString = "...";
        });
    }
}

context.Services.Configure方法是獲取選項類的通用方法。它還需要一個委託來設定選項值。在此示例中,我們通過在指定的 lambda 表示式中設定SenderConnectionString屬性來進行配置。

AbpModule基類提供了一個Configure方法作為context.Services.Configure方法的快捷方式,因此您可以重寫程式碼如下:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    Configure<AzureSmsServiceOptions>(options =>
    {
        options.Sender = "+901112223344";
        options.ConnectionString = "...";
    });
}

你應該看到了一點點區別了吧?

使用配置選項值

ASP.NET Core 提供了一個IOptions<T>介面來注入選項類。我們使用AzureSmsServiceOptions重寫AzureSmsService裡的IConfiguration服務,如以下程式碼塊所示:
public class AzureSmsService : ISmsService, ITransientDependency
{

private readonly AzureSmsServiceOptions _options;
    public AzureSmsService(IOptions<AzureSmsServiceOptions> options)
    {
        _options = options.Value;
    }
    
    public async Task SendAsync(string phoneNumber, string message)
    {
        string sender = _options.Sender;
        string ConnectionString = _options.ConnectionString;
        //TODO...
    }
}

我們注入IOptions<AzureSmsServiceOptions>並使用其Value屬性來獲取配置值。IOptions<T>介面定義在Microsoft.Extensions.Options包裡,是一種標準的選項類注入方式,如果你直接注入AzureSmsServiceOptions類,你會得到一個依賴注入異常。所以要通過IOptions<T>把選項類包裹起來.

上面只是簡單地定義、配置和使用了這些選項。如果我們想結合配置系統來設定選項該怎麼辦?
首先,我們用IConfiguration讀取配置,並設定選項值:

[DependsOn(typeof(SmsSendingModule))]
public class MyStartupModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var configuration = context.Services.GetConfiguration();        
        Configure<AzureSmsServiceOptions>(options =>
        {
            options.Sender =  configuration\["AzureSmsService:Sender"\];
            options.ConnectionString = configuration\["AzureSmsService:ConnectionString"\];
        });
    }
}

我們通過上下文的context.Services.GetConfiguration()方法獲得IConfiguration介面,然後進行賦值操作。
由於這種用法很常見,我們可以重寫一下程式碼,如下塊所示:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    var configuration = context.Services.GetConfiguration();    
    Configure<AzureSmsServiceOptions>(configuration.GetSection("AzureSmsService"));
}

[success] 翻譯點評:雖然改動量很小,但是非常漂亮,可見作者精益求精的態度。

使用這種用法,配置代替了委託操作,它通過命名約定自動將配置鍵與選項類的屬性進行匹配。如果AzureSmsService未在配置中定義,則此程式碼也不會影響選項。

選項模式為開發人員提供了更大的靈活性:他們可以從IConfiguration或者其他資料來源進行選項設定。

[success] 提示:預設情況下從配置中設定選項

如果您正在構建可重用模組,最好儘可能從配置中設定選項。也就是說,您可以將前面的程式碼寫入您的模組中。這樣,開發人員可以直接從appsettings.json檔案中配置他們的模組。

ASP.NET Core 和 ABP 選項

ASP.NET Core 和 ABP 框架都集中預先使用選項模式配置選項。

以下示例顯示了在 ABP 框架中配置選項:

Configure<AbpAuditingOptions>(options =>
{
    options.IgnoredTypes.Add(typeof(ProductDto));
});

AbpAuditingOptions由 ABP 框架的審計日誌系統定義。我們正在新增一個型別,用於在審計日誌中忽略ProductDto

下一個示例顯示在 ASP.NET Core 中配置選項:

Configure<MvcOptions>(options =>
{
    options.RespectBrowserAcceptHeader = true;
});

MvcOptions由 ASP.NET Core 內部定義,用於配置 ASP.NET Core MVC 框架的行為。

選項類中的複雜型別

請注意,AbpAuditingOptions.IgnoredTypes是一個的Type列表,它不是在appsettings.json檔案中定義的那種簡單原始型別,這是選項模式的好處之一:您可以定義具有複雜型別的屬性甚至回撥動作。

配置和選項系統提供了一種便捷的方式來配置服務的行為。

日誌系統

日誌記錄是每個應用的基礎設施。ASP.NET Core 提供了一個簡單而高效的日誌系統。它可以與流行的日誌庫整合,例如 NLog、Log4Net 和 Serilog。

Serilog 是一個廣泛使用的庫,它為日誌目標提供了許多選項,包括控制檯、文字檔案和 Elasticsearch。ABP 啟動模板帶有預安裝和配置的 Serilog 庫。它將日誌寫入應用的Logs資料夾中,如果需要,您可以配置 Serilog 以將日誌寫入不同的目標(所有配置都包含在啟動模板中)。請參考 Serilog 的官方文件來配置 Serilog 選項。

Serilog 不是 ABP 框架的核心依賴,因此,我們可以輕鬆使用其他提供商進行替換。

ILogger<T>介面用於在 ASP.NET Core 中寫入日誌,T通常是您的服務型別。

下面是一個寫入日誌的示例服務:

public class AzureSmsService : ISmsService, ITransientDependency
{
    private readonly ILogger<AzureSmsService> _logger;
    public AzureSmsService(ILogger<AzureSmsService> logger)
    {
        _logger = logger;
    }
    public async Task SendAsync(string phoneNumber, string message)
    {
        _logger.LogInformation($"Sending SMS to {phoneNumber}: {message}");
        //TODO...
    }
}

該類在其建構函式中注入ILogger<AzureSmsService>服務並使用LogInformation方法將日誌寫入日誌系統。

ILogger介面上有更多的方法可以寫入不同嚴重級別的日誌,例如LogError和LogDebug。有關所有詳細資訊,請參閱 ASP.NET Core 的文件日誌系統

概括

本文介紹了 ASP.NET Core 和 ABP 框架的核心模組。

你已經瞭解瞭如何使用Startup類、配置系統和選項模式來配置 ASP.NET Core 和 ABP 框架服務。

ABP 提供了一個模組化系統,相比 ASP.NET Core 的初始化和配置,ABP支援建立多個模組,其中每個模組支援獨立的初始化和配置。通過這種方式,您可以將應用拆分為多個模組,以更好地方式組織程式碼或建立在不同應用中可重用的模組。

依賴注入系統是ASP.NET Core 最基本的基礎設施。一個服務通常使用依賴注入系統消費其他服務。這裡介紹了依賴注入系統的基本方面,並解釋了 ABP 如何簡化服務註冊。

下一篇講重點介紹資料訪問基礎架構,這是業務應用程式的一個重要方面。我們將看到 ABP 框架如何標準化定義實體和使用儲存庫來抽象和執行資料庫操作,同時自動化資料庫連線和事務管理。

相關文章