I think, Retic's approach is not so bad.
Lets continue on his answer and extract the database configuration into a separate method ConfigureMongoDb:
public void ConfigureServices(IServiceCollection services)
{
ConfigureMongoDb(services);
services.AddControllers()
.AddNewtonsoftJson(options => options.UseMemberCasing());
}
private void ConfigureMongoDb(IServiceCollection services)
{
var settings = GetMongoDbSettings();
var db = CreateMongoDatabase(settings);
var collectionA = db.GetCollection<Author>(settings.AuthorsCollectionName);
services.AddSingleton(collectionA);
services.AddSingleton<AuthorService>();
var collectionB = db.GetCollection<Book>(settings.BooksCollectionName);
services.AddSingleton(collectionB);
services.AddSingleton<BookService>();
}
private BookstoreDatabaseSettings GetMongoDbSettings() =>
Configuration.GetSection(nameof(BookstoreDatabaseSettings)).Get<BookstoreDatabaseSettings>();
private IMongoDatabase CreateMongoDatabase(BookstoreDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
return client.GetDatabase(settings.DatabaseName);
}
or in a more compact form:
private void ConfigureMongoDb(IServiceCollection services)
{
var settings = GetMongoDbSettings();
var db = CreateMongoDatabase(settings);
AddMongoDbService<AuthorService, Author>(settings.AuthorsCollectionName);
AddMongoDbService<BookService, Book>(settings.BooksCollectionName);
void AddMongoDbService<TService, TModel>(string collectionName)
{
services.AddSingleton(db.GetCollection<TModel>(collectionName));
services.AddSingleton(typeof(TService));
}
}
The downside with this approach is, that all mongodb related instances (except the services) are created at startup.
This is not always bad, because in the case of wrong settings or other mistakes you get immediate response on startup.
If you want lazy initialization for this instances, you can register the database creation and the collection retrieval with a factory method:
public void ConfigureMongoDb(IServiceCollection services)
{
var settings = GetMongoDbSettings();
services.AddSingleton(_ => CreateMongoDatabase(settings));
AddMongoDbService<AuthorService, Author>(settings.AuthorsCollectionName);
AddMongoDbService<BookService, Book>(settings.BooksCollectionName);
void AddMongoDbService<TService, TModel>(string collectionName)
{
services.AddSingleton(sp => sp.GetRequiredService<IMongoDatabase>().GetCollection<TModel>(collectionName));
services.AddSingleton(typeof(TService));
}
}
In the service you have to inject just the registered collection.
public class BookService
{
private readonly IMongoCollection<Book> _books;
public BookService(IMongoCollection<Book> books)
{
_books = books;
}
}
public class AuthorService
{
private readonly IMongoCollection<Author> _authors;
public AuthorService(IMongoCollection<Author> authors)
{
_authors = authors;
}
}
MongoClientin your services? learn.microsoft.com/en-us/aspnet/core/fundamentals/…