简体   繁体   English

自托管 .NET 核心控制台应用程序中的 Startup.cs

[英]Startup.cs in a self-hosted .NET Core Console Application

I have a self-hosted .NET Core Console Application .我有一个自托管的.NET 核心控制台应用程序

The web shows examples for ASP.NET Core but I do not have a web server. web 显示了ASP.NET Core的示例,但我没有 web 服务器。 Just a simple command line application.只是一个简单的命令行应用程序。

Is it possible to do something like this for console applications?是否可以为控制台应用程序做这样的事情?

public static void Main(string[] args)
{
    // I don't want a WebHostBuilder. Just a command line

    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

I would like to use a Startup.cs like in ASP.NET Core but on console.我想在 ASP.NET Core 中使用 Startup.cs,但在控制台上。

How do I to this?我该怎么办?

So i came across with this solution, inspired by the accepted answer:所以我遇到了这个解决方案,灵感来自公认的答案:

Program.cs程序.cs

public class Program
{
    public static void Main(string[] args)
    {
        IServiceCollection services = new ServiceCollection();
        // Startup.cs finally :)
        Startup startup = new Startup();
        startup.ConfigureServices(services);
        IServiceProvider serviceProvider = services.BuildServiceProvider();

        //configure console logging
        serviceProvider
            .GetService<ILoggerFactory>()
            .AddConsole(LogLevel.Debug);

        var logger = serviceProvider.GetService<ILoggerFactory>()
            .CreateLogger<Program>();

        logger.LogDebug("Logger is working!");

        // Get Service and call method
        var service = serviceProvider.GetService<IMyService>();
        service.MyServiceMethod();
    }
}

Startup.cs启动文件

public class Startup
{
    IConfigurationRoot Configuration { get; }

    public Startup()
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");

        Configuration = builder.Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLogging();
        services.AddSingleton<IConfigurationRoot>(Configuration);
        services.AddSingleton<IMyService, MyService>();
    }
}

appsettings.json appsettings.json

{
    "SomeConfigItem": {
        "Token": "8201342s223u2uj328",
        "BaseUrl": "http://localhost:5000"
    }
}

MyService.cs我的服务.cs

public class MyService : IMyService
{
    private readonly string _baseUrl;
    private readonly string _token;
    private readonly ILogger<MyService> _logger;

    public MyService(ILoggerFactory loggerFactory, IConfigurationRoot config)
    {
        var baseUrl = config["SomeConfigItem:BaseUrl"];
        var token = config["SomeConfigItem:Token"];

        _baseUrl = baseUrl;
        _token = token;
        _logger = loggerFactory.CreateLogger<MyService>();
    }

    public async Task MyServiceMethod()
    {
        _logger.LogDebug(_baseUrl);
        _logger.LogDebug(_token);
    }
}

IMyService.cs IMyService.cs

public interface IMyService
{
    Task MyServiceMethod();
}

This answer is based on the following criteria:此答案基于以下标准:

I'd like to use the new Generic Host CreateDefaultBuilder without any of the ASP.NET web stuff, in a simple console app, but also be able to squirrel away the startup logic in startup.cs in order to configure AppConfiguration and Services我想在一个简单的控制台应用程序中使用没有任何 ASP.NET web 内容的新通用主机CreateDefaultBuilder ,但也能够在startup.csAppConfiguration启动逻辑以配置AppConfiguration和服务

So I spent the morning figuring out how you could do such a thing.所以我花了一个上午的时间来研究如何做这样的事情。 This is what I came up with...这是我想出来的……

The only nuget package this method requires is Microsoft.Extensions.Hosting (at the time of this writing it was at version 3.1.7 ).此方法需要的唯一 nuget 包是Microsoft.Extensions.Hosting (在撰写本文时,它的版本为3.1.7 )。 Here is a link to the nuget package .这是nuget 包的链接。 This package is also required to use CreateDefaultBuilder() , so chances are you already had it added.这个包也需要使用CreateDefaultBuilder() ,所以你很可能已经添加了它。

After you add the extension (extension code at bottom of answer) to your project, you set your program entry to look similar to this:将扩展(答案底部的扩展代码)添加到项目后,将程序条目设置为类似于以下内容:

using Microsoft.Extensions.Hosting;

class Program
{
    static async Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        await host.RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseStartup<Startup>(); // our new method!
}

You add a Startup.cs that should look like this:您添加一个Startup.cs ,它应该如下所示:

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // Configure your services here
    }
}

You then configure your services as you would in a typical ASP.NET Core application (without needing to have ASP.NET Core Web Hosting installed).然后,您可以像在典型的 ASP.NET Core 应用程序中一样配置您的服务(无需安装 ASP.NET Core Web Hosting)。

Demo Project演示项目

I put together a .NET Core 3.1 consoledemo project doing all kinds of things such as an IHostedService implementation, BackgroundService implementation, transient/singleton services.我整理了一个 .NET Core 3.1 控制台演示项目,用于执行各种操作,例如IHostedService实现、 BackgroundService实现、瞬态/单例服务。 I also injected in IHttpClientFactory and IMemoryCache for good measure.我还注入了IHttpClientFactoryIMemoryCache以进行很好的衡量。

Clone that repo and give it a shot.克隆该 repo 并试一试。

How It Works这个怎么运作

I created a IHostBuilder extension method which simply implements the IHostBuilder UseStartup<TStartup>(this IHostBuilder hostBuilder) pattern that we are all used to.我创建了一个IHostBuilder扩展方法,它只是实现了我们都习惯的IHostBuilder UseStartup<TStartup>(this IHostBuilder hostBuilder)模式。

Since CreateDefaultBuilder() adds in all the basics , there's not much left to add to it.由于CreateDefaultBuilder() 添加了所有基础知识,因此没有太多可添加的内容。 The only thing we are concerned about is getting the IConfiguration and creating our service pipeline via ConfigureServices(IServiceCollection) .我们唯一关心的是通过ConfigureServices(IServiceCollection)获取IConfiguration并创建我们的服务管道。

Extension Method Source Code扩展方法源代码

/// <summary>
/// Extensions to emulate a typical "Startup.cs" pattern for <see cref="IHostBuilder"/>
/// </summary>
public static class HostBuilderExtensions
{
    private const string ConfigureServicesMethodName = "ConfigureServices";

    /// <summary>
    /// Specify the startup type to be used by the host.
    /// </summary>
    /// <typeparam name="TStartup">The type containing an optional constructor with
    /// an <see cref="IConfiguration"/> parameter. The implementation should contain a public
    /// method named ConfigureServices with <see cref="IServiceCollection"/> parameter.</typeparam>
    /// <param name="hostBuilder">The <see cref="IHostBuilder"/> to initialize with TStartup.</param>
    /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
    public static IHostBuilder UseStartup<TStartup>(
        this IHostBuilder hostBuilder) where TStartup : class
    {
        // Invoke the ConfigureServices method on IHostBuilder...
        hostBuilder.ConfigureServices((ctx, serviceCollection) =>
        {
            // Find a method that has this signature: ConfigureServices(IServiceCollection)
            var cfgServicesMethod = typeof(TStartup).GetMethod(
                ConfigureServicesMethodName, new Type[] { typeof(IServiceCollection) });

            // Check if TStartup has a ctor that takes a IConfiguration parameter
            var hasConfigCtor = typeof(TStartup).GetConstructor(
                new Type[] { typeof(IConfiguration) }) != null;

            // create a TStartup instance based on ctor
            var startUpObj = hasConfigCtor ?
                (TStartup)Activator.CreateInstance(typeof(TStartup), ctx.Configuration) :
                (TStartup)Activator.CreateInstance(typeof(TStartup), null);

            // finally, call the ConfigureServices implemented by the TStartup object
            cfgServicesMethod?.Invoke(startUpObj, new object[] { serviceCollection });
        });

        // chain the response
        return hostBuilder;
    }
}

All .NET Core applications are composed of well-crafted independent libraries and packages which you're free to reference and use in any type of application.所有.NET Core应用程序都由精心设计的独立库和包组成,您可以在任何类型的应用程序中自由引用和使用它们。 It just so happens that an Asp.net core application comes preconfigured to reference a lot of those libraries and exposes an http endpoint.碰巧的是, Asp.net core应用程序预先配置为引用许多这些库并公开一个 http 端点。

But if it's Dependency Injection you need for your console app, simply reference the appropriate library.但是,如果您的控制台应用程序需要依赖注入,只需引用相应的库即可。 Here's a guide: https://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/这是一个指南: https : //andrewlock.net/using-dependency-injection-in-a-net-core-console-application/

Another way would be using HostBuilder from Microsoft.Extensions.Hosting package.另一种方法是使用Microsoft.Extensions.Hosting包中的HostBuilder

public static async Task Main(string[] args)
{
    var builder = new HostBuilder()
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.SetBasePath(Directory.GetCurrentDirectory());
            config.AddJsonFile("appsettings.json", true);
            if (args != null) config.AddCommandLine(args);
        })
        .ConfigureServices((hostingContext, services) =>
        {
            services.AddHostedService<MyHostedService>();
        })
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConfiguration(hostingContext.Configuration);
            logging.AddConsole();
        });

    await builder.RunConsoleAsync();
}

I know this thread is kinda old, but I decided to share my code anyway, since it also accomplishes the end Daniel wanted (DI in a Console Application), but without a Startup class.我知道这个线程有点旧,但我还是决定分享我的代码,因为它也实现了 Daniel 想要的(控制台应用程序中的 DI),但没有 Startup 类。 Ps.: Note that this solution is valid either for .NET Core or .NET Framework. Ps.:请注意,此解决方案适用于 .NET Core 或 .NET Framework。

Program.cs:程序.cs:

public class Program
    {

        public static void Main(string[] args)
        {
            var services = new ServiceCollection();

            DependencyInjectionConfiguration.ConfigureDI(services);

            var serviceProvider = services.BuildServiceProvider();

            var receiver = serviceProvider.GetService<MyServiceInterface>();

            receiver.YourServiceMethod();
        }
    }

public static class DependencyInjectionConfiguration
    {
        public static void ConfigureDI(IServiceCollection services)
        {
            services.AddScoped<MyServiceInterface, MyService>();
            services.AddHttpClient<MyClient>(); // for example
        }
    }

I came across the same problem and I think this is a good solution:我遇到了同样的问题,我认为这是一个很好的解决方案:

class Program
{
    static async Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        await host.RunAsync();
    }

     public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostBuilderContext, serviceCollection) => new Startup(hostBuilderContext.Configuration).ConfigureServices(serviceCollection))
}

Yes, it is.是的。 ASP.NET Core applications can either be self-hosted - as in your example - or hosted inside a web server such as IIS. ASP.NET Core 应用程序可以是自托管的(如您的示例中所示),也可以托管在 Web 服务器(如 IIS)中。 In .NET Core all apps are console apps.在 .NET Core 中,所有应用程序都是控制台应用程序。

You can resolve it easier.您可以更轻松地解决它。 Just make 2 files, and edit Main method:只需制作 2 个文件,然后编辑 Main 方法:

Startup.cs启动文件

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
(...)
 public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
            loggerFactory.AddDebug();


            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action}");
            });
        }
    }

YourService.cs YourService.cs

using Microsoft.AspNetCore.Mvc;
(...)
public class MyeasynetworkController : Controller
    {
        [HttpGet]
        public IActionResult Run()
        {

            return Ok("Im Working");
        }
    }

and edit your static void Main(string[] args)并编辑您的静态 void Main(string[] args)

            var host = new WebHostBuilder()
                .UseKestrel()
                .UseUrls("http://+:5000")
                .UseStartup<Startup>()
                .Build();

            host.Run();

then open http://localhost:5000/Myeasynetwork/Run and you should see http status 200 response with plain text Im Working然后打开http://localhost:5000/Myeasynetwork/Run ,你应该看到 http status 200 响应,纯文本我正在工作

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

相关问题 ASP.NET 核心空白应用startup.cs - ASP.NET Core blank application startup.cs .net 核心 Startup.cs CreateScope 或 BuildServiceProvider - .net core Startup.cs CreateScope or BuildServiceProvider 自托管 Net Core 3 应用程序不采取端口设置 - Self-hosted Net Core 3 application does not take port settings .NET Core program.cs 和 Startup.cs 未命中 - .NET Core program.cs and Startup.cs not hit 在我的.Net框架应用程序中,“startup.cs”(.Net Core)的等价物是什么? - what is the equivalent of “startup.cs”(.Net Core) in my .Net framework application? 如何在我的 ASP.NET Core 应用程序中使用 Startup.cs 之外的服务? - How can I use a service outside of Startup.cs in my ASP.NET Core Application? 如何在登录 .net core 3.1 Web 应用程序时在 startup.cs 中设置全局数据? - How to set global data in startup.cs upon logging in .net core 3.1 web application? 在ASP.NET CORE中的Startup.cs中设置动态变量 - Set Dynamic Variables in Startup.cs in ASP.NET CORE 在Startup.cs .net core 2.1中加载程序集 - Load assembly in Startup.cs .net core 2.1 如何在 ASP.NET Core 中的 Startup.cs 中注册 RoleManager - How to register RoleManager in Startup.cs in ASP.NET Core
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM