You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向WebApplicationBuilder注入无公共构造函数的单例类?

解决方案

直接使用带工厂委托的服务注册重载,手动返回你实现的单例实例即可,正确的注册代码如下:

// 注册IUserDB服务,生命周期匹配单例行为设为Singleton
builder.Services.AddSingleton<IUserDB>(_ => FakeUserDB.GetInstance());
// MyUserStore的注册保持原有写法即可正常工作
builder.Services.AddTransient<IUserStore<MyUser>, MyUserStore>();

问题原因

  • 你之前使用的AddScoped<IUserDB, FakeUserDB>()是基于类型的自动实例化注册方式,这种模式下DI容器会尝试调用类的公开构造函数创建实例,但你的FakeUserDB构造函数被声明为private,容器没有访问权限,自然会出现解析失败的问题。
  • 你手写的FakeUserDB是经典的单例实现,全局只会存在一个实例,因此注册生命周期必须指定为Singleton和它的行为匹配,如果误用Scoped/Transient生命周期,可能出现实例被容器意外释放、跨作用域校验异常等问题。

可选优化方案

如果不需要严格保留手写单例的逻辑,完全可以删掉FakeUserDB里自行维护的instance字段和GetInstance()静态方法,把构造函数改为公开,直接交给DI容器托管单例生命周期,这是.NET项目里更推荐的写法,不需要自己处理单例的线程安全问题:

public class FakeUserDB : IUserDB
{
  // 公开构造函数,容器可直接访问
  public FakeUserDB()
  {
  }

  public string? GetPasswordHash(string username)
  {
    return "idk something";
  }
}

对应的注册代码更简洁:

builder.Services.AddSingleton<IUserDB, FakeUserDB>();
builder.Services.AddTransient<IUserStore<MyUser>, MyUserStore>();

内容的提问来源于stack exchange,提问作者iggy12345

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:12:11