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

标签 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 中是私有(private)的,它用于将内容反序列化为结构化模型将在整个网络服务生命周期中提供附加功能:

// 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; }

}

Controller 看起来像这样:

[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

任何 Controller /api 调用中的哈希码: enter image description here

GetHashCode() 方法没有被篡改。 这会导致源自 appsettings.json 的配置未在 Controller /api 调用中应用,所有属性都使用其默认值/null 进行实例化。

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

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

最佳答案

因为这个调用:

services.AddSingleton(runtimeServices);

注册 RuntimeServices 的一个实例, 它不配置 IOptions<RuntimeServices> .所以,当你要求 IOptions<RuntimeServices> ,没有,您将获得一个具有所有默认值的新实例。

你想要:

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

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

关于c# - 使用 IServiceCollection.AddSingleton() 的单个对象实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51768185/

相关文章:

c# - ASP.NET 5 身份 - 自定义 SignInManager

c# - 如何在 Startup.cs 之外设置数据库连接字符串用户名和密码?

asp.net-core - 检测来自 .NET 核心中间件的静态文件请求

c# - WebAPI OData v4 查询不是异步的?

c# - 用字符串和整数解析文件c#

c# - 线程安全 List<T>.Remove 创建的 System.ArgumentOutOfRangeException

azure - 如何不从用户 secret 配置中获取空值?

.net - .Net 4.6 可以在 linux 上运行吗

c# - 如何在 C# 应用程序中启用 MMCSS?

c# - Entity Framework Scaffold-DbContext 用户登录失败