问题描述
我在创建控制台程序以调用引用的类库中的enroll方法时遇到麻烦。除了配置,我无法注入依赖项。
Class库包含要调用的代码:
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