I'm having trouble creating a console program to call the enrol method in referenced class library. I cannot get the dependencies injected except the config.
The Class library contains the code to call:
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
}
}
And the console program
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();
}
}
}
I tried adding in
services.AddSingleton<HttpClient>(new HttpClient());
to get the HttpCLient injected but to no avail.
Any help appreciated or advice on testing the call to DoSomething in the referenced project
You're not configuring your Logger
and HttpClient
in services
. You are also likely missing an additional Nuget package, Microsoft.Extensions.Logging.Console
- install that if it's missing, since you mentioned this is a Console App
Modify your code as follows:
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);
}
Also, very important : remove your empty constructor in MyClient
! You never want that one hit, In fact, it's far better for the program to crash in debugging than hit that constructor, as it will create appearance of working - like the situation you're in now.
The reason your code "didn't do anything different" when you added the services.AddSingleton<HttpClient>(new HttpClient());
code is because of your empty constructor - since the Logger
service was still not configured, DI framework couldn't match the correct constructor - so instead of getting a meaningful error, the empty constructor ran (since it always matches) - causing debugging pain and suffering .
As an aside, I recommend reading up on how DI works underneath (maybe even build out your own DI container, a very simple one, for practice. Do not use your own DI container in production.), This is a good article: by the guy that practically invented this stuff: https://martinfowler.com/articles/injection.html
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.