Reputation: 51
I have a project .Net Core in React and, to save time, I would like to test a method to export files by a Console Application. But I can't to implement the DI in my console, here's the error:
Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger`1[MyPrj.Managers.Managers.Implementations.MyLogManager]' while attempting to activate 'MyPrj.Managers.Managers.Implementations.MyLogManager'.
This is a simplified version of my Program.cs:
class Program
{
public static IConfigurationRoot Configuration;
public static ServiceProvider serviceProvider;
public static void Main(string[] args)
{
var services = new ServiceCollection();
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(AppContext.BaseDirectory))
.AddJsonFile("appsettings.json", optional: true);
Configuration = builder.Build();
services.AddDbContext<MyDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.Configure<MailOptions>(Configuration.GetSection("EmailSettings"));
[... other options...]
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<ILogManager, MyLogManager>();
services.AddScoped<IMailManager, MailManager>();
[... other services ...]
services.AddScoped<IDocumentationManager, DocumentationManager>();
serviceProvider = services.BuildServiceProvider();
MainAsync().GetAwaiter().GetResult();
Console.WriteLine("END");
Console.ReadKey();
}
private static async Task MainAsync()
{
await ExportAsync();
}
public static async Task ExportAsync()
{
using (MyDBContext dbContext = serviceProvider.GetService<MyDBContext>())
{
List<User> user = dbContext.Users.ToList();
var logger = serviceProvider.GetService<ILogManager>();
var docManager = serviceProvider.GetService<IDocumentationManager>();
string userAnswer = Console.ReadLine();
var file = await docManager.GetUser(userAnswer);
File.WriteAllBytes("C:\tmp\user.txt", file.File);
}
}
}
Upvotes: 0
Views: 2851
Reputation: 51
Thanks to all,
it has been enough adding services.AddLogging()
, following @Steven 's advice, to solve my problem.
Upvotes: 1
Reputation: 338
You can use a HostedService for encapsulating the StartAsync and StopAsync, making the code more elegancy.
public class HostedService : IHostedService
{
private readonly ISolrSeeder _seeder;
public HostedService(ISolrSeeder seeder)
{
_seeder = seeder;
}
public async Task StartAsync(CancellationToken cancellationToken)
=> await _seeder.SeedAsync(cancellationToken);
public async Task StopAsync(CancellationToken cancellationToken) =>
await Task.Run(() => Environment.Exit(Environment.ExitCode), cancellationToken);
}
And then, you can make your program.cs
represents the startup from a console application, considering many environments.
internal class Program
{
private const string SettingsName = "appsettings";
private const string SettingsExtention = ".json";
private const string AppSettings = SettingsName + SettingsExtention;
public static async Task Main(string[] args)
=> await new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettings, true, true)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettings, true, true)
.AddJsonFile(SettingsName + "." + hostContext.HostingEnvironment.EnvironmentName + SettingsExtention, true, true)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services
.AddLogging()
.AddRepositories()
.AddDbContext(options => options.ConnectionString = hostContext.Configuration.GetConnectionString("DefaultConnection"))
.AddSolr(options =>
{
options.BaseAddress = hostContext.Configuration["Solr:BaseAddress"];
options.Core = hostContext.Configuration["Solr:Core"];
})
.AddScoped<ISolrSeeder, SolrSeeder>()
.AddHostedService<HostedService>();
})
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
The rest of the code is available on this repository.
Upvotes: 1
Reputation: 2565
Since you are creating your console app from scratch you have to manually configure the logger, otherwise it would not be injected.
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
services.AddSingleton<ILoggerFactory>(loggerFactory);
public class MyLogManager : ILogManager {
private readonly ILogger<MyLogManager> logger;
public MyLogManager(ILoggerFactory factory) {
logger = factory.CreateLogger<MyLogManager>();
}
}
you can find more here https://learn.microsoft.com/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1
Upvotes: 4