158 lines
4.0 KiB
Markdown
158 lines
4.0 KiB
Markdown
# Options Pattern - Hướng dẫn sử dụng
|
|
|
|
## Tổng quan
|
|
|
|
Options Pattern là cách tiếp cận **Strongly-Typed** để quản lý cấu hình trong .NET, thay vì sử dụng `IConfiguration` trực tiếp với magic strings.
|
|
|
|
## Lợi ích
|
|
|
|
1. **Type Safety**: IntelliSense hỗ trợ, tránh lỗi chính tả
|
|
2. **Validation**: Validate cấu hình ngay khi khởi động ứng dụng
|
|
3. **Separation of Concerns**: Tách biệt Infrastructure (config) khỏi Application logic
|
|
4. **Testability**: Dễ dàng mock và test
|
|
|
|
## Cách sử dụng trong Service
|
|
|
|
### Ví dụ: Sử dụng JwtOptions trong Service
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.Options;
|
|
using MyNewProjectName.Infrastructure.Options;
|
|
|
|
public class JwtTokenService
|
|
{
|
|
private readonly JwtOptions _jwtOptions;
|
|
|
|
// Inject IOptions<JwtOptions> thay vì IConfiguration
|
|
public JwtTokenService(IOptions<JwtOptions> jwtOptions)
|
|
{
|
|
_jwtOptions = jwtOptions.Value;
|
|
}
|
|
|
|
public string GenerateToken()
|
|
{
|
|
// Sử dụng với IntelliSense hỗ trợ
|
|
var secretKey = _jwtOptions.SecretKey;
|
|
var issuer = _jwtOptions.Issuer;
|
|
var expiration = _jwtOptions.ExpirationInMinutes;
|
|
|
|
// ... logic tạo token
|
|
return token;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Ví dụ: Sử dụng DatabaseOptions
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.Options;
|
|
using MyNewProjectName.Infrastructure.Options;
|
|
|
|
public class DatabaseService
|
|
{
|
|
private readonly DatabaseOptions _dbOptions;
|
|
|
|
public DatabaseService(IOptions<DatabaseOptions> dbOptions)
|
|
{
|
|
_dbOptions = dbOptions.Value;
|
|
}
|
|
|
|
public string GetConnectionString()
|
|
{
|
|
return _dbOptions.DefaultConnection;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Các Options Classes có sẵn
|
|
|
|
1. **DatabaseOptions** - Cấu hình kết nối database
|
|
2. **JwtOptions** - Cấu hình JWT authentication
|
|
3. **RedisOptions** - Cấu hình Redis cache
|
|
4. **SerilogOptions** - Cấu hình Serilog logging
|
|
|
|
## Thêm Options Class mới
|
|
|
|
### Bước 1: Tạo Options Class
|
|
|
|
```csharp
|
|
// MyNewProjectName.Infrastructure/Options/EmailOptions.cs
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
|
namespace MyNewProjectName.Infrastructure.Options;
|
|
|
|
public class EmailOptions
|
|
{
|
|
public const string SectionName = "Email";
|
|
|
|
[Required]
|
|
public string SmtpServer { get; set; } = string.Empty;
|
|
|
|
[Range(1, 65535)]
|
|
public int SmtpPort { get; set; } = 587;
|
|
|
|
[Required]
|
|
[EmailAddress]
|
|
public string FromAddress { get; set; } = string.Empty;
|
|
}
|
|
```
|
|
|
|
### Bước 2: Đăng ký trong DependencyInjection.cs
|
|
|
|
```csharp
|
|
// Trong MyNewProjectName.Infrastructure/DependencyInjection.cs
|
|
services.Configure<EmailOptions>(configuration.GetSection(EmailOptions.SectionName));
|
|
|
|
// Validate (optional)
|
|
services.AddOptions<EmailOptions>()
|
|
.Bind(configuration.GetSection(EmailOptions.SectionName))
|
|
.ValidateDataAnnotations()
|
|
.ValidateOnStart();
|
|
```
|
|
|
|
### Bước 3: Thêm vào appsettings.json
|
|
|
|
```json
|
|
{
|
|
"Email": {
|
|
"SmtpServer": "smtp.gmail.com",
|
|
"SmtpPort": 587,
|
|
"FromAddress": "noreply@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Bước 4: Sử dụng trong Service
|
|
|
|
```csharp
|
|
public class EmailService
|
|
{
|
|
private readonly EmailOptions _emailOptions;
|
|
|
|
public EmailService(IOptions<EmailOptions> emailOptions)
|
|
{
|
|
_emailOptions = emailOptions.Value;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Validation
|
|
|
|
Options classes sử dụng Data Annotations để validate:
|
|
|
|
- `[Required]` - Bắt buộc phải có giá trị
|
|
- `[MinLength]` - Độ dài tối thiểu
|
|
- `[Range]` - Giá trị trong khoảng
|
|
- `[EmailAddress]` - Định dạng email
|
|
- Và nhiều attributes khác...
|
|
|
|
Nếu validation fail, ứng dụng sẽ **không khởi động** và báo lỗi rõ ràng.
|
|
|
|
## IOptions vs IOptionsSnapshot vs IOptionsMonitor
|
|
|
|
- **IOptions<T>**: Giá trị được cache, không tự động reload khi config thay đổi
|
|
- **IOptionsSnapshot<T>**: Tự động reload khi config thay đổi (scoped)
|
|
- **IOptionsMonitor<T>**: Tự động reload và có thể subscribe để nhận thông báo (singleton)
|
|
|
|
Thông thường, sử dụng **IOptions<T>** là đủ.
|