c# - 使用 DI 模拟调用 .Net Core 类库
问题描述
我无法创建一个控制台程序来调用引用类库中的注册方法。除了配置之外,我无法注入依赖项。
类库包含要调用的代码:
public interface IMyClient
{
Task DoSomething(Request request);
}
public class MyClient : IMyClient
{
private readonly MyClientConfig _config;
private readonly ILogger<MClient> _logger;
private readonly HttpClient _client;
public MyClient()
{
}
public MyClient(MyClientConfig config, ILogger<MyClient> logger, HttpClient client)
{
_config = config;
_logger = logger;
_client = client;
}
public async Task DoSomething(Request request)
{
// BREAKPOINT HERE HAS config (id = 1) but logger & client are null
}
}
和控制台程序
class Program
{
private static IServiceProvider _serviceProvider;
static void Main(string[] args)
{
RegisterServices();
IServiceScope scope = _serviceProvider.CreateScope();
var request = new Request()
{
Id = 1
};
scope.ServiceProvider.GetRequiredService<IMyClient>().DoSomething(request);
DisposeServices();
}
private static void RegisterServices()
{
var myClientConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.Build().GetSection("MyClient").Get<MyClientConfig>();
var services = new ServiceCollection();
services.AddSingleton<IMyClient, MyClient>();
services.AddSingleton<IMyClientConfig>(myClientConfig);
_serviceProvider = services.BuildServiceProvider(true);
}
private static void DisposeServices()
{
if (_serviceProvider == null)
{
return;
}
if (_serviceProvider is IDisposable)
{
((IDisposable)_serviceProvider).Dispose();
}
}
}
我尝试添加
services.AddSingleton<HttpClient>(new HttpClient());
获取 HttpCLient 注入但无济于事。
任何有关在引用项目中测试对 DoSomething 的调用的帮助或建议
解决方案
您没有配置您的Logger
和HttpClient
在services
. 您还可能缺少一个额外的 Nuget 包,Microsoft.Extensions.Logging.Console
如果缺少,请安装它,因为您提到这是一个控制台应用程序
修改您的代码如下:
private static void RegisterServices()
{
var myClientConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.Build().GetSection("MyClient").Get<MyClientConfig>();
var services = new ServiceCollection();
services.AddSingleton<IMyClient, MyClient>();
// Configure logging service
services.AddLogging(cfg => cfg.AddConsole())
.AddTransient<MyClient>();
// Configure HttpClient - might need some constructor params, depending on your use case
services.AddSingleton<HttpClient>(new HttpClient());
_serviceProvider = services.BuildServiceProvider(true);
}
另外,非常重要:删除你的空构造函数MyClient
!你永远不想要那一击!事实上,让程序在调试中崩溃比点击构造函数要好得多,因为它会产生工作的外观——就像你现在所处的情况一样。
添加代码时您的代码“没有做任何不同”的原因services.AddSingleton<HttpClient>(new HttpClient());
是因为您的构造函数为空- 因为Logger
服务仍未配置,DI 框架无法匹配正确的构造函数 - 所以不是得到一个有意义的错误,空的构造函数运行(因为它总是匹配) - 导致调试痛苦和痛苦。
顺便说一句,我建议阅读 DI 如何在下面工作(甚至可以构建自己的 DI 容器,一个非常简单的容器,用于练习。不要在生产中使用自己的 DI 容器!)。这是一篇好文章,作者实际上是发明了这些东西:https ://martinfowler.com/articles/injection.html
推荐阅读
- html - 将数据数组作为帖子发送到 django
- post - 将正文“表单数据”添加到 Power Query 中的发布请求 - Power BI
- html - 自定义 Bootstrap 的汉堡菜单
- javascript - Firebase:通过 GitHub 登录/注册
- jenkins - 当每个文件都应该符合标准时,为什么詹金斯会说“没有找到工件”?
- c++ - MPI::Boost 编译问题
- algorithm - 我能猜出 RDP (Ramer-Douglas-Peucker) 的合适 epsilon 吗?
- html - 将日期字段的默认输入区域更改为文本值日期
- c - librdkafka 生产者从函数中获取消息并在主题上生成它
- javascript - 如何根据 React 中的索引停止在循环中运行的计数器