ASP.NET 核心 2.1 - 选项模式 - 访问选项不会 return 绑定的实例 class

ASP.NET Core 2.1 - Options pattern - accessing options doesn't return instance of the bound class

我正在尝试按照 this example from Microsoft Docs 从我的 ASP.NET Core 2.1 应用程序中的 appsettings.json 文件中检索一些配置选项。

我绑定了class

public class MailServer
{
    public string Host { get; set; }
    public int Port { get; set; }
    public bool UseSSL { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string FromAddress { get; set; }
    public MailServer()
    {
    }
}

到Startup.cs中的配置

public void ConfigureServices(IServiceCollection services)
{
    // .....
    services.Configure<MailServer>(Configuration.GetSection("MailServer"));
    // .....
    services.AddSingleton<IScheduledTask, ScheduledTask>();
}

在启动时,我还添加了 ScheduledTask 作为单例,以便从特定的 class 访问上下文 - 这也是我想访问选项的地方。

public interface IScheduledTask
{
    void MonitorCloudHosts();
}

public class ScheduledTask : IScheduledTask
{
    private readonly IServiceProvider _ServiceProvider;
    private readonly MailServer _mailServer;

    // note here you ask to the injector for IServiceProvider
    public ScheduledTask(IServiceProvider serviceProvider, IOptions<MailServer> optionsAccessor)
    {
        _ServiceProvider = serviceProvider;
        _mailServer = optionsAccessor.Value;
    }

    public void MonitorCloudHosts()
    {
        // Do some stuff
        var xyz = _mailServer.Host;
    }
}

这是我的 appsettings.json 文件:

  {
    "Logging": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "AllowedHosts": "*",
    "ConnectionStrings": {
      "CloudMonitorConnection": "Server=.\SQLEXPRESS;Database=CloudMonitor;Integrated Security=SSPI;MultipleActiveResultSets=true;",
      "HangFireConnection": "Server=.\SQLEXPRESS;Database=HangFire;Integrated Security=SSPI;"
    },
    "MailServer": {
      "Host": "smtp.gmail.com",
      "Port": "587",
      "UseSSL": "True",
      "Username": "xxxxxxx@gmail.com",
      "Password": "xxxxxxx",
      "FromAddress": "xxxxxxx<xxxxxxx@gmail.com>"
    }
  }

编译器在调用 _mailServer.Host 时给出错误说 "An object reference is required..." - 但在 optionsAccessor.Value.

上没有给出错误

不应该 optionsAccessor.Value return MailServer 的实例吗?我在这里犯了一些新手错误吗?

属性 MailServer class 的 UseSSLbool 但在 appsettings.json 中设置为 "True"

您应该这样更改 appsettings.json:

"MailServer": {
  "Host": "smtp.gmail.com",
  "Port": 587,
  "UseSSL": true,
  "Username": "xxxxxxx@gmail.com",
  "Password": "xxxxxxx",
  "FromAddress": "xxxxxxx<xxxxxxx@gmail.com>"
}

编辑: 我用这段代码创建了一个空项目并进行了编译。可能是using statement出错了,或者开启了严格模式?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace samp
{
    public class MailServer
    {
        public string Host { get; set; }
        public int Port { get; set; }
        public bool UseSSL { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string FromAddress { get; set; }
        public MailServer()
        {
        }
    }

    public interface IScheduledTask
    {
        void MonitorCloudHosts();
    }

    public class ScheduledTask : IScheduledTask
    {
        private readonly IServiceProvider _ServiceProvider;
        private readonly MailServer _mailServer;

        // note here you ask to the injector for IServiceProvider
        public ScheduledTask(IServiceProvider serviceProvider, IOptions<MailServer> optionsAccessor)
        {
            _ServiceProvider = serviceProvider;
            _mailServer = optionsAccessor.Value;
        }

        public void MonitorCloudHosts()
        {
            // Do some stuff
            var xyz = _mailServer.Host;
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.Configure<MailServer>(Configuration.GetSection("MailServer"));
            services.AddSingleton<IScheduledTask, ScheduledTask>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}