【问题标题】:ASP.NET Core Singleton Service created multiple times多次创建 ASP.NET Core Singleton Service
【发布时间】:2019-06-26 22:44:35
【问题描述】:

我正在开发一个 ASP.NET Core 2.1 项目,我需要在该项目中注册,然后在 Startup.ConfigureServices 中使用单例服务。

我有以下代码:

public void ConfigureServices(IServiceCollection services)
{
    //....
    //....

    services.AddSingleton<IMyService,MyService>();

    var serviceProvider = services.BuildServiceProvider();

    var myService = serviceProvider.GetService<IMyService>();

    services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));
}

上面的代码对我来说很好,可以在 ConfigureServices 中使用“MyService”。然而,稍后在我的应用程序中,当我尝试使用 MyService 时,再次调用 MyService 的构造函数。为什么它不使用自从我使用AddSingleton 注册类以来已经创建的实例?

编辑:我决定编辑以添加我的最终目标,看看是否有不同的方法来完成它。我的单例服务提供了对可能来自 2 个不同地方的一些设置的访问。其中一项设置是数据库连接字符串。我需要 ConfigureServices 中的连接字符串,所以当我调用 services.AddDbContext 时我就有了。我还想在获取配置设置的服务中进行一些日志记录,这意味着我也需要获取 ILoggerFactory。

【问题讨论】:

  • 因为它们是从两个不同的服务提供商那里调用的。您在 configure services 方法中手动构建的一个,以及在该方法超出范围后由框架构建的一个。
  • 在早期版本中,您可能刚刚返回了您从配置服务构建的提供程序,但我不确定在最新版本的 asp.net 核心中是否已更改。
  • @Nkosi 我在原始帖子中添加了一个编辑,以表明我正在尝试做什么。也许有不同的方法可以做到这一点?
  • @Nkosi 我还没有真正尝试过其他任何东西,因为我什至不知道从哪里开始。
  • 这可能是XY problem

标签: c# asp.net-core dependency-injection


【解决方案1】:

ConfigureServices 调用BuildServiceProvider 将导致创建一个额外的单例服务副本。

在这种特殊情况下,请使用另一种方法来推迟对服务提供商的访问。 AddDbContext 有一个允许这种情况的重载,其中服务提供者作为选项操作委托的一部分提供。

//...

services.AddSingleton<IMyService, MyService>();

services.AddDbContext<MyDbContext>((serviceProvider, options) =>
    options.UseMySql(serviceProvider.GetRequiredService<IMyService>().DBConnectionString)
);

//....

参考AddDbContext&lt;TContext&gt;(IServiceCollection, Action&lt;IServiceProvider,DbContextOptionsBuilder&gt;, ServiceLifetime, ServiceLifetime)

【讨论】:

    【解决方案2】:

    AddSingleton 告诉 Unity 构建一次。该“一次”是您在代码中直接调用的任何构造函数的补充。

    如果您想重复使用您创建的实例,请改用AddInstance

    var serviceProvider = services.BuildServiceProvider();
    
    var myService = serviceProvider.GetService<IMyService>();
    
    services.AddInstance<IMyService>(myService);
    
    services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));
    

    【讨论】:

    • 是否可以在将IMyService 添加到services 之前从serviceProvider 获取实例?
    猜你喜欢
    • 1970-01-01
    • 2018-07-29
    • 2018-04-28
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 2023-04-06
    • 2019-05-10
    • 1970-01-01
    相关资源
    最近更新 更多