简体   繁体   English

如何在.Net核心控制台应用程序中实现依赖注入

[英]How to implement Dependency Injection in .Net core Console Application

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.我在 React 中有一个 project.Net Core,为了节省时间,我想测试一种通过控制台应用程序导出文件的方法。 But I can't to implement the DI in my console, here's the error:但我无法在控制台中实现 DI,这是错误:

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'.尝试激活“MyPrj.Managers.Managers.Implementations.MyLogManager”时无法解析类型“Microsoft.Extensions.Logging.ILogger`1[MyPrj.Managers.Managers.Implementations.MyLogManager]”的服务。

This is a simplified version of my Program.cs:这是我的 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);
        }
    }
}

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://docs.microsoft.com/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1你可以在这里找到更多https://docs.microsoft.com/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1

You can use a HostedService for encapsulating the StartAsync and StopAsync , making the code more elegancy.您可以使用HostedService来封装StartAsyncStopAsync ,使代码更加优雅。

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.然后,考虑到许多环境,您可以让您的program.cs代表从控制台应用程序启动。

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 .代码的 rest 可在此存储库中找到。

Thanks to all, it has been enough adding services.AddLogging() , following @Steven 's advice , to solve my problem.感谢所有人,按照@Steven 的建议添加services.AddLogging()已经足够解决我的问题了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM