I have an interface that I'm using between a UserStore
and the database of my users:
public interface IUserDB
{
// simplified for brevity
string? GetPasswordHash(string username);
}
And a singleton that implements this (for testing purposes):
public class FakeUserDB : IUserDB
{
private static FakeUserDB instance;
private FakeUserDB()
{
}
public static FakeUserDB GetInstance()
{
if (instance == null) instance = new FakeUserDB();
return instance;
}
public string? GetPasswordHash(string username)
{
return "idk something";
}
}
Now I have a UserStore
that communicates with this singleton, that is passed in via the constructor:
public class MyUserStore : IUserStore<MyUser>, IUserPasswordStore<MyUser>, IUserTwoFactorStore<MyUser>,
IUserLockoutStore<MyUser>, IUserRoleStore<MyUser>, IUserClaimStore<MyUser>
{
private readonly string _connectionString;
private readonly IUserDB _userDB;
public MyUserStore(IConfiguration configuration, IUserDB db)
{
_connectionString = configuration.GetConnectionString("DefaultConnection");
_userDB = db;
}
// A lot more stuff goes below here
// ....
}
I'm aware that I need to add this as a dependency injection to my program.cs, but I'm not sure how to do so because FakeUserDB
doesn't have a public constructor. When I try:
builder.Services.AddScoped<IUserDB, FakeUserDB>();
builder.Services.AddTransient<IUserStore<MyUser>, MyUserStore>();
It doesn't work. Is there a way that I can add a singleton service to my builder?
CodePudding user response:
Instead of implementing the class as a singleton, you can leave that to the IoC container:
public class FakeUserDB : IUserDB
{
public FakeUserDB()
{
}
public string? GetPasswordHash(string username)
{
return "idk something";
}
}
In the IoC, you register it as a singleton:
builder.Services.AddSingleton<IUserDB, FakeUserDB>();
builder.Services.AddTransient<IUserStore<MyUser>, MyUserStore>();
As an alternative, if you do not want or cannot change the class, you can register the instance with a factory method like this:
builder.Services.AddSingleton<IUserDB>(prov => FakeUserDB.GetInstance());
builder.Services.AddTransient<IUserStore<MyUser>, MyUserStore>();