如何在ASP.NET Core MVC 5中使用不可变对象

利用仅初始化设置程序,使配置选项在ASP.NET Core MVC 5中不可变,以避免不必要的分配并消除出现错误的机会。

如何在ASP.NET Core MVC 5中使用不可变对象

不变性使代码随着时间的推移更易于编写,测试和维护。但是,许多编程语言不支持不变性。直到最近,C#才开箱即用地支持不变性。这在C#9中会有所变化。

现在,您可以利用仅初始化属性将应用程序选项配置为不可变实例。毕竟,它们基本上是应用程序常数。您不希望在应用程序的生存期内更改它们。

本文讨论了不可变的对象,为什么我们要使我们的配置信息不可变,以及如何在ASP.NET Core MVC 5中实现这一点。

若要使用本文提供的代码示例,您应该在系统中安装Visual Studio 2019。如果您还没有副本,则可以在此处下载Visual Studio 2019如何在ASP.NET Core MVC 5中使用不可变对象

在Visual Studio 2019中创建ASP.NET Core MVC 5项目

首先,让我们在Visual Studio中创建一个ASP.NET Core项目。按照这些步骤将在Visual Studio 2019中创建一个新的ASP.NET Core MVC 5项目。

  1. 启动Visual Studio IDE。
  2. 点击“创建新项目”。
  3. 在“创建新项目”窗口中,从显示的模板列表中选择“ ASP.NET Core Web App(模型-视图-控制器)”。
  4. 点击下一步。
  5. 在“配置新项目”窗口中,指定新项目的名称和位置。
  6. 根据您的喜好,可以选择选中“将解决方案和项目放在同一目录中”复选框。
  7. 点击下一步。
  8. 在接下来显示的“其他信息”窗口中,从顶部的下拉列表中选择.NET 5.0作为目标框架。将“身份验证类型”保留为“无”(默认)。
  9. 确保未选中“启用Docker”,“配置HTTPS”和“启用Razor运行时编译”复选框,因为在此我们将不使用任何这些功能。
  10. 单击创建。

将创建一个新的ASP.NET Core MVC 5项目。我们将在本文的后续部分中使用该项目。

什么是不可变的对象?

不可变对象定义为创建后不能更改的对象。字符串是C#中不可变类型的示例。创建字符串对象后,您将无法更改它。当您尝试更改字符串对象时,会在内存中创建一个新的字符串实例,并在其中包含新数据。

相比之下,StringBuilder的实例是可变对象。C#中的StringBuilder是可变的字符序列,可以根据需要扩展为存储更多字符。与更改字符串不同,更改StringBuilder实例不会在内存中创建新实例。

对于许多用例,例如数据库配置元数据类,不变性是理想的功能。不变性的另一个用例是数据传输对象DTO)。DTO实例通常被序列化,因此它可以独立于用户端使用的技术。自然地,当在数据库和客户端之间传输数据对象时,您要确保不能更改该对象-这正是DTO的目的。

您还可以在C#中拥有不可变的集合。不可变集合是类型的集合,其成员在创建后就不能更改。要使用不可变集合,应在项目中安装System.Collection.Immutable NuGet包。您可以阅读我以前的文章更不可变的集合在这里

使IOptions在ASP.NET Core MVC 5中不可变

ASP.NET Core MVC 5中工作时,通常会将应用程序的设置存储在诸如appsettings.json之类的文件中,然后在应用程序需要它们时将其读回。要读取应用程序中的那些设置,可以使用IOptions <T>在Startup类的ConfigureServices方法中利用依赖项注入。

现在考虑以下代码片段,该片段显示了一个名为DbConfiguration的类,该类用于存储数据库配置信息。

   public class DbConfiguration
    {
        public string Server { get; init; }
        public string Provider { get; init; }
        public string Database { get; init; }
        public int Port { get; init; }
        public string UserName { get; init; }
        public string Password { get; init; }
    }

请注意上面每个数据库配置属性的仅初始化设置器的声明。仅初始化设置器允许您以通常的方式设置这些值,但是这些属性在其初始构造完成后将变为只读。

您可以在appsettings.json文件中指定数据库配置信息,如下所示。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "DbConfiguration": {
    "Server": "Server01",
    "Provider": "Provider01",
    "Database": "Database01",
    "Port": 1433,
    "UserName": "User01",
    "Password": "Password01"
  },
  "AllowedHosts": "*"
}

以下代码段显示了如何将appsettings.json文件中指定的数据库配置信息绑定到DbConfiguration的实例。

services.Configure<DbConfiguration> (options =>
   Configuration.GetSection("DbConfiguration").Bind(options)); 

或者,您可以使用以下代码进行绑定,然后将数据库配置实例添加为单例服务。

var dbConfiguration = new DbConfiguration();
Configuration.Bind("DbConfiguration", dbConfiguration);
services.AddSingleton(dbConfiguration);

这是ConfigureServices方法的完整代码供您参考:

public void ConfigureServices(IServiceCollection services)
{
   services.AddControllersWithViews();
   services.Configure<DbConfiguration> (options =>
   Configuration.GetSection("DbConfiguration").Bind(options));
} 

ASP.NET Core MVC 5中的控制器中读取配置数据

在HomeController类中,声明一个DbConfiguration类型的只读实例变量,如下所示。

private readonly DbConfiguration _dbConfiguration; 

要从控制器访问DbConfiguration实例,我们将利用构造注入,如下面的代码片段所示。

public HomeController(ILogger<HomeController> logger, IOptions<DbConfiguration> dbConfiguration)
{
   _logger = logger;
   _dbConfiguration = dbConfiguration.Value;
}

注意上面构造函数的参数中IOptions <DbConfiguration>实例的用法。使用Value属性在构造函数中初始化名为_dbConfiguration的DbConfiguration实例。

如果现在尝试将值分配给DbConfiguration实例的任何init-only属性或索引器,则将看到下面的图1所示的编译时错误消息。

ASPNET核心MVC不可变的配置
图1。

这正是我们想要实现的目标。名为_dbConfiguration的DbConfiguration实例是不可变的。您可以从其属性读取值,但不能以任何方式更改其任何属性的值。

从C#9开始,您可以使用init访问器来代替属性和索引器的set访问器。这样做将确保这些属性是只读的。您只能在创建它们所属的类的实例时将值分配给这些属性。

原创文章,作者:冰封一夏,如若转载,请注明出处:http://www.nncjzx.com/1373.html

关注本站公众号获取更多实时内容

本站微信公众号:二线码农