# 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à đủ.
