【问题标题】:Single object instance using IServiceCollection.AddSingleton()使用 IServiceCollection.AddSingleton() 的单个对象实例
【发布时间】:2018-08-09 21:32:58
【问题描述】:

考虑以下简单的 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() 中的哈希码:

任何控制器/api调用中的哈希码:

GetHashCode() 方法未被篡改。 这导致配置原始表单 appsettings.json 未在控制器/api 调用中应用,所有属性都使用其默认值 / null 进行实例化。

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

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

【问题讨论】:

    标签: c# asp.net-core


    【解决方案1】:

    因为这个电话:

    services.AddSingleton(runtimeServices);
    

    注册RuntimeServices 的实例,它不配置IOptions&lt;RuntimeServices&gt;。因此,当您请求 IOptions&lt;RuntimeServices&gt; 时,没有,您会得到一个具有所有默认值的新实例。

    你想要:

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

    2. 删除AddSingleton调用并使用services.Configure&lt;RuntimeServices&gt;(_configuration)

    【讨论】:

    • 谢谢,我应该阅读更多关于 IOptions 界面的内容。我测试了您的解决方案,它按预期工作,非常感谢您的及时响应!现在我为创建这个线程超过 10 分钟感到愚蠢......
    猜你喜欢
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    相关资源
    最近更新 更多