推荐4个.NET 库,总有用得上的时候

作者:微信公众号:【架构师老卢】
8-2 8:57
18

概述:2014 年,Microsoft 宣布他们打算发布已经流行的 .NET Framework 的开源继任者:.NET Core。这是一项重大举措,不久之后,.NET 源代码在 GitHub 上发布。宣布 .NET Core 将成为 .NET 所有未来版本的基础,并由 .NET 基金会指导进行开源贡献。.NET Core 取得了重大成功。随着 2020 年 .NET 5 的发布,.NET Framework 和 .NET Core 合并为单一的开源跨平台技术。向开源的转变围绕 .NET 平台培养了一个蓬勃发展的社区。许多有才华的人为该平台发布了高质量的工具和库,这些工具和库每天都使开发人员的生活更

2014 年,Microsoft 宣布他们打算发布已经流行的 .NET Framework 的开源继任者:.NET Core。这是一项重大举措,不久之后,.NET 源代码在 GitHub 上发布。宣布 .NET Core 将成为 .NET 所有未来版本的基础,并由 .NET 基金会指导进行开源贡献。

.NET Core 取得了重大成功。随着 2020 年 .NET 5 的发布,.NET Framework 和 .NET Core 合并为单一的开源跨平台技术。

向开源的转变围绕 .NET 平台培养了一个蓬勃发展的社区。许多有才华的人为该平台发布了高质量的工具和库,这些工具和库每天都使开发人员的生活更轻松。

我是开源的坚定支持者,更是反对不重新发明轮子。在这篇文章中,我将概述 4 个绝对最好的库,我根本离不开。大多数时候,我通过安装这些来开始任何新项目。

**1. Refit **

传统上,在 .NET 中处理 HTTP 请求需要大量的手动代码和样板代码。开发人员必须手动处理构造 HTTP 请求、处理标头、管理响应和执行反序列化等细节。

这通常是通过 HttpClient 类的某种自定义实现来完成的:

public class Program  
{  
    private static readonly HttpClient client = new HttpClient();  
  
    public static async Task Main(string[] args)  
    {  
        var user = await GetUserAsync(123);  
        Console.WriteLine($"User Name: {user.Name}");  
    }  
  
    private static async Task<User> GetUserAsync(int userId)  
    {  
        // Set the base address and default headers if needed  
        client.BaseAddress = new Uri("https://api.example.com/");  
        client.DefaultRequestHeaders.Accept.Clear();  
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  
        // Make the HTTP request  
        var response = await client.GetAsync($"users/{userId}");  
        response.EnsureSuccessStatusCode(); // Throws if not 200-299  
  
        // Deserialize the response body  
        var responseBody = await response.Content.ReadAsStringAsync();  
        return JsonConvert.DeserializeObject\<User>(responseBody);  
    }  
}

它可能很麻烦、重复且难以阅读。

取而代之的是,Refit 通过将您的 REST API 转换为实时接口来为您处理所有这些。

只需定义您的接口:

public interface IMyApi  
{  
    [Get("/users/{userId}")]  
    Task<User> GetUserAsync(int userId);  
}

将服务注入到您需要的任何位置,并使用它来发出 HTTP 请求。

public class UsersController : ControllerBase  
{  
    private readonly IMyApi _myApi;  
  
    public UsersController(IMyApi myApi)  
    {  
        _myApi = myApi;  
    }  
  
    [HttpGet("{id}")]  
    public async Task<IActionResult> GetUser(int id)  
    {  
        var user = await _myApi.GetUserAsync(id);  
        return Ok(user);  
    }  
}

在引擎盖下,Refit 将使用所有最佳实践和标准为您搭建必要的代码。您需要做的就是定义接口,其余的都会得到处理。

您的所有 HTTP 调用都被分离到简化的、可维护的部分中,避免了样板代码。系统会为您处理序列化和反序列化,并且会为您检查 API 调用的编译时类型。这意味着您可以及早发现潜在错误,从而在运行时避免它们。Refit 还具有高度可定制性,可以轻松定制以处理自定义标题、参数等。

2. Coravel

Coravel 是一个优秀的库,它使繁重的任务,如调度、排队、缓存、后台作业和事件广播变得非常简单和直观。Coravel是一个庞大的图书馆,处理许多不同的领域。

具体来说,我喜欢使用它的调度功能。您很少构建不必处理某种重复性任务的系统。也许您必须每小时将数据卸载到第三方系统一次,或者您必须每晚凌晨 12 点进行数据库备份。Coravel 提供了一种接近零的配置方法来处理此类任务,并且比主要云提供商提供的解决方案更易于维护。

只需定义一个继承自 IInvocable 接口的任务。Coravel 中的可调用项仅表示 Coravel 可以在应用程序的不同部分使用的特定任务。在这里,您可以放置要按计划运行的实际业务逻辑。

using Coravel.Invocable;  
using System;  
using System.Threading.Tasks;  
  
public class MyScheduledTask : IInvocable  
{  
    public Task Invoke()  
    {  
        // Your logic here  
        Console.WriteLine($"Executing scheduled task at: {DateTime.Now}");  
        return;  
    }  
}

现在,只需在您的Program.cs中注册Coravel调度器服务,并指定您希望任务运行的时间和频率。

using Coravel;  
using Microsoft.AspNetCore.Builder;  
using Microsoft.Extensions.DependencyInjection;  
using Microsoft.Extensions.Hosting;  
  
var builder = WebApplication.CreateBuilder(args);  
  
// Add services to the container.  
builder.Services.AddControllers();  
builder.Services.AddEndpointsApiExplorer();  
builder.Services.AddSwaggerGen();  
  
// Add Coravel services  
builder.Services.AddScheduler();  
  
// Register the invocable task  
builder.Services.AddTransient<MyScheduledTask>();  
  
var app = builder.Build();  
  
// Configure the HTTP request pipeline.  
if (app.Environment.IsDevelopment())  
{  
    app.UseSwagger();  
    app.UseSwaggerUI();  
}  
  
app.UseHttpsRedirection();  
app.UseAuthorization();  
app.MapControllers();  
  
// Schedule the invocable task  
var provider = app.Services;  
  
provider.UseScheduler(scheduler =>  
{  
    scheduler.Schedul\<MyScheduledTask>().EveryMinute();  
});  
  
app.Run();

大功告成。在幕后,Coravel 将搭建脚手架并处理按计划运行任务所需的代码。它可以设置为完全按照您所需的时间间隔运行,如果您愿意,甚至可以接受 CRON 表达式。

请务必在 Github 上为 Coravel 加星标。

3. FluentValidation

FluentValidation 是一个常用的 .NET 库,它简化了在 .NET 应用程序中定义和执行验证规则的过程。传统上,.NET 中的数据验证是一项繁重的任务,需要您使用自定义逻辑或不灵活的数据注释来增加类。

取而代之的是,FluentValidation 允许开发人员通过提供一个接口来促进可定制的验证实现,从而摆脱必须编写验证逻辑的担忧。FluentValidation 的界面允许您以与自然语言非常相似的方式定义验证规则,而无需编写冗长且重复的验证代码,这些代码很快就会变得难以管理。这极大地提高了代码的可读性,并使未来的开发人员更容易理解和维护。

首先定义一个继承自 AbstractValidator 的类,然后使用 RuleFor 方法定义验证规则。

public class Customer  
{  
    public string Name { get; set; }  
    public int Age { get; set; }  
    public string Email { get; set; }  
}  
  
public class CustomerValidator : AbstractValidator<Customer>  
{  
    public CustomerValidator()  
    {  
        RuleFor(customer => customer.Name)  
            .NotEmpty().WithMessage("Name is required.");  
        RuleFor(customer => customer.Age)  
            .InclusiveBetween(18, 60).WithMessage("Age must be between 18 and 60.");  
        RuleFor(customer => customer.Email)  
            .EmailAddress().WithMessage("Invalid email address.");  
    }  
}

FluentValidation 附带了许多方便的预定义验证方法,例如 .EmailAddress()、.NotEmpty()、.GreaterThan() 和 .CreditCard(),但也可以处理您自己的自定义验证逻辑

定义后,CustomerValidator 可用于在必要时验证任何客户对象。

var customer = new Customer { Name = "", Age = 25, Email = "invalid-email" };  
var validator = new CustomerValidator();  
var result = validator.Validate(customer);  
  
if (!result.IsValid)  
{  
    foreach (var failure in result.Errors)  
    {  
        Console.WriteLine($"Property {failure.PropertyName} failed validation. Error: {failure.ErrorMessage}");  
    }  
}

4. Polly

Polly 是一个流行的弹性和故障处理库,可以显着提高应用程序的鲁棒性。它允许开发人员定义不同的策略,以促进重试逻辑、熔断、超时、隔板隔离和回退,从而提高软件的可靠性。

在编写软件时,不可避免地会发生异常和临时错误。例如,您的程序在其生命周期内的某个时刻将不可避免地遇到网络超时。如果没有一种优雅的方法来处理这些情况,应用程序的关键业务方面可能会受到影响。这就是波莉的闪光点。polly 中的策略是高度模块化的,可以进行组合以解决最复杂的错误处理方案。

例如,您可以将重试策略与熔断机制和回退策略相结合,以创建可靠的故障处理策略。

假设您有一个从外部 API 获取数据的服务,并且您希望使此调用能够灵活应对暂时性故障:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Polly;
using Polly.CircuitBreaker;
using Polly.Fallback;
using Polly.Retry;

class Program
{
    static async Task Main(string[] args)
    {
        // Define the retry policy
        var retryPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

        // Define the circuit breaker policy
        var circuitBreakerPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .CircuitBreakerAsync(3, TimeSpan.FromSeconds(30));

        // Define the fallback policy
        var fallbackPolicy = Policy<HttpResponseMessage>
            .Handle<BrokenCircuitException>()
            .OrResult(r => !r.IsSuccessStatusCode)
            .FallbackAsync(
                new HttpResponseMessage(System.Net.HttpStatusCode.OK) 
                { 
                    Content = new StringContent("{\"message\": \"Fallback response\"}") 
                },
                onFallbackAsync: async b =>
                {
                    Console.WriteLine("Executing fallback logic...");
                });

        // Combine the policies
        var combinedPolicy = fallbackPolicy.WrapAsync(circuitBreakerPolicy).WrapAsync(retryPolicy);

        using (var httpClient = new HttpClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "https://external-api.com/data");

            try
            {
                // Execute the request with the combined policy
                HttpResponseMessage response = await combinedPolicy.ExecuteAsync(() => httpClient.SendAsync(request));

                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine("Request succeeded!");
                    // Process the response
                    string data = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(data);
                }
                else
                {
                    Console.WriteLine("Request failed with status code: " + response.StatusCode);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occurred: " + ex.Message);
            }
        }
    }
}

我们首先定义我们需要的三个策略;重试策略、熔断策略和回退策略。

如果遇到不成功的状态代码,重试策略将尝试重试失败的 HTTP 请求最多三次。重试采用指数退避策略进行间隔,这意味着重试之间的时间越多,操作失败的次数越多,重试之间的时间就越长。

熔断机制策略的工作原理是在连续三次尝试失败后停止执行。一旦发生这种情况,30 秒内将不再尝试,让系统有机会恢复,然后再试一次。

阅读排行