c# - 基于 .NET Core 3.1 中的泛型类型通过 DI 注入应用程序设置
问题描述
我正在努力为我的 MongoDB 客户端创建一个基础服务。在我的 DI 容器中,我从application.json
(根据Microsoft 的 MongoDB 教程)注入了数据库连接设置)注入了数据库连接设置。
我想不通的是基于传递给基本服务的构造函数的泛型类型来访问这些设置属性之一的最佳方法。
例如,Type 的 MongoDB 集合名称Player
命名为Players。我的一个想法是不要typeof(T)
将键/值放在设置中,而是将集合名称与类型名称结合起来。
这是注入的数据库设置对象:
public class GameDatabaseSettings : IGameDatabaseSettings
{
public string PlayersCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
public string LobbiesCollectionName { get; set; }
}
应用程序json:
"GameDatabaseSettings": {
"PlayersCollectionName": "Players",
"LobbiesCollectionName": "Lobbies",
"ConnectionString": "mongodb+srv://bugbeeb:*******@csharptest-yzm6y.mongodb.net/test?retryWrites=true&w=majority",
"DatabaseName": "DiceGameDB"
},
以下是基本服务的运作方式:
public interface IGameItem
{
public string Id { get; set; }
}
public class BaseService<T> where T:IGameItem
{
private readonly IMongoCollection<T> _collection;
public BaseService(IGameDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var db = client.GetDatabase(settings.DatabaseName);
_collection = db.GetCollection<T>(settings.CollectionName); //<-- How to make this T specific??
}
public virtual async Task<T> GetAsync(string id)
{
var result = await _collection.FindAsync(item => item.Id == id);
return result.FirstOrDefault();
}
public virtual async Task DeleteAsync(string id)
{
await _collection.FindOneAndDeleteAsync(item => item.Id == id);
}
}
解决方案
你在正确的轨道上typeof(T)
。您缺少的唯一步骤是您可以将您的键/值对列表绑定appSettings.json
到Dictionary<string, string>
您的GameDatabaseSettings
.
这将使您可以根据字符串名称查找配置值,从而允许您Type
通过appSettings.json
.
所以给出以下内容appSettings.json
:
"GameDatabaseSettings": {
"CollectionNames": {
"Players": "Players",
"Lobbies": "Lobbies"
},
"ConnectionString": "mongodb+srv://bugbeeb:*******@csharptest-yzm6y.mongodb.net/test?retryWrites=true&w=majority",
"DatabaseName": "DiceGameDB"
}
}
您可以绑定到设置对象,例如:
public class GameDatabaseSettings : IGameDatabaseSettings
{
public Dictionary<string, string> CollectionNames { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
现在,在您的服务中,您应该能够执行以下操作:
_collection = db.GetCollection<T>(settings.CollectionNames[typeof(T).Name]);
当然,您不应该假设将配置正确的映射,因此您可能希望编写更多的防御性代码,类似于:
_collection = db.GetCollection<T>(
settings.CollectionNames.TryGetValue(
typeof(T).Name,
out var collectionName
)?
collectionName :
throw new ConfigurationError(
$"The ‘{typeof(T).Name}’ mapping is not configured as part of {nameof(GameDatabaseSettings)}."
)
);
推荐阅读
- java - 我的列表视图未显示(Android Studio)
- docker - Docker:如何让 BrowserSync 在 CraftCMS 容器上运行?
- scikit-learn - scikitlearn 中高斯过程中的超参数优化
- android - 如何将语言值传递给 url 以在 android studio 中进行翻译
- javascript - 刷新页面后useEffect运行api请求
- apache-flink - Flink keyby/window operator 任务执行地点和内部结构
- google-cloud-platform - 如何从监控 API 中获取指标样本
- vb.net - 更好的解决方案,计时器,秒表,时间跨度
- pandas - 将新列逐个值添加到数据框,给定数据框大小未知
- firebase - 如何调用使用 ExpressJS 和 cloud_functions 的 Firebase Cloud Function