使用IServiceCollection.AddSingleton()的单个对象实例

时间:2018-08-09 13:20:56

标签: c# asp.net-core

考虑以下简单的appsettings.json:

{
  "maintenanceMode": true
}

它已加载到我的Startup.cs / Configure(...)方法中

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    // Load appsettings.json config
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    _configuration = builder.Build();

    // Apply static dev / production features
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    // Other features / settings
    app.UseHttpsRedirection();
    app.UseMvc();
}

_configuration在Startup.cs内部是私有的,用于将内容反序列化为结构化模型,该模型将在整个Web服务生存期内提供附加功能

// 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.AddOptions();

    var runtimeServices = _configuration.Get<RuntimeServices>();

    services.AddSingleton(runtimeServices);
}

模型如下:

public class RuntimeServices {

    [JsonProperty(PropertyName = "maintenanceMode")]
    public bool MaintenanceMode { get; set; }

}

控制器看起来像这样:

[ApiController]
public class ApplicationController : Base.Controller {

    private readonly RuntimeServices _services;

    public ApplicationController(IOptions<RuntimeServices> services) : base(services) {
        _services = services.Value;
    }

    // Web-api following ...

}

现在是问题所在:

在appsettings.json加载并反序列化后,启动时,RuntimeServices实例将保存所有正确的信息(是的,此处省略了其中的某些信息)。

Startup.cs / ConfigureServices()中的哈希码: enter image description here

任何控制器/ api调用内的哈希码: enter image description here

GetHashCode()方法尚未被篡改。 这导致未在控制器/ api调用中应用源自配置形式appsettings.json的配置,所有属性均以其默认值/ null实例化。

我希望使用AddSingleton()方法注入非常相同实例,并在应用程序的整个生命周期内重复使用它。有人可以告诉我为什么要创建RuntimeServices的新实例吗?以及如何在Startup.cs中拥有对象的可用实例而仍然在控制器中访问同一对象实例的目标呢?

我的首选解决方案将是通常的单例模式。但是我希望使用asp.net核心提供的内置功能来解决此问题。

1 个答案:

答案 0 :(得分:4)

因为这个电话:

services.AddSingleton(runtimeServices);

注册RuntimeServices的实例,但不配置IOptions<RuntimeServices>。因此,当您请求IOptions<RuntimeServices>时,没有请求,并且您将获得一个具有所有默认值的新实例。

您想要:

  1. 保持AddSingleton并使用public ApplicationController(RuntimeServices services)

  2. 删除AddSingleton呼叫并使用services.Configure<RuntimeServices>(_configuration)