Dan*_*iel 44 c# console-application .net-core
我有一个自托管的.NET Core Console应用程序.
Web显示ASP.NET Core的示例,但我没有Web服务器.只是一个简单的命令行应用程序
是否可以为控制台应用程序执行此类操作?
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();
}
Run Code Online (Sandbox Code Playgroud)
我想在ASP.NET Core中使用Startup.cs,但是在控制台上.
怎么样?
Dan*_*iel 63
所以我遇到了这个解决方案,受到了接受的答案的启发:
Program.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();
}
}
Run Code Online (Sandbox Code Playgroud)
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>();
}
}
Run Code Online (Sandbox Code Playgroud)
appsettings.json
{
"SomeConfigItem": {
"Token": "8201342s223u2uj328",
"BaseUrl": "http://localhost:5000"
}
}
Run Code Online (Sandbox Code Playgroud)
MyService.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);
}
}
Run Code Online (Sandbox Code Playgroud)
IMyService.cs
public interface IMyService
{
Task MyServiceMethod();
}
Run Code Online (Sandbox Code Playgroud)
And*_*ndy 45
此答案基于以下标准:
我想
CreateDefaultBuilder在一个简单的控制台应用程序中使用没有任何 ASP.NET web 内容的新通用主机,但也能够松散启动逻辑startup.cs以便配置AppConfiguration和服务
所以我花了一个上午的时间来研究如何做这样的事情。这是我想出来的……
此方法需要的唯一 nuget 包是Microsoft.Extensions.Hosting(在撰写本文时它是 version 3.1.7)。这是nuget 包的链接。这个包也需要使用CreateDefaultBuilder(),所以你很可能已经添加了它。
将扩展(答案底部的扩展代码)添加到项目后,将程序条目设置为类似于以下内容:
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!
}
Run Code Online (Sandbox Code Playgroud)
你添加一个Startup.cs应该是这样的:
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// Configure your services here
}
}
Run Code Online (Sandbox Code Playgroud)
然后像在典型的 ASP.NET Core 应用程序中一样配置服务(无需安装 ASP.NET Core Web Hosting)。
我整理了一个 .NET Core 3.1 控制台演示项目,用于IHostedService执行各种操作,例如实现、BackgroundService实现、瞬态/单例服务。我也注射了IHttpClientFactory并IMemoryCache采取了很好的措施。
克隆该 repo 并试一试。
我创建了一个IHostBuilder扩展方法,它只是实现了IHostBuilder UseStartup<TStartup>(this IHostBuilder hostBuilder)我们都习惯的模式。
由于CreateDefaultBuilder() 添加了所有基础知识,因此没有什么可添加的了。我们唯一关心的是IConfiguration通过ConfigureServices(IServiceCollection).
/// <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;
}
}
Run Code Online (Sandbox Code Playgroud)
Ara*_*edi 23
所有.NET Core应用程序都由精心设计的独立库和包组成,您可以在任何类型的应用程序中自由引用和使用它们.事实上,Asp.net core应用程序预先配置为引用许多这些库并公开http端点.
但是,如果您的控制台应用程序需要依赖注入,只需引用相应的库即可.这是一个指南:http://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/
我知道这个线程有点旧,但我还是决定分享我的代码,因为它也实现了 Daniel 想要的(控制台应用程序中的 DI),但没有 Startup 类。Ps.:请注意,此解决方案适用于 .NET Core 或 .NET Framework。
程序.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
}
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用HostBuilderfrom Microsoft.Extensions.Hosting包。
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();
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我遇到了同样的问题,我认为这是一个很好的解决方案:
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))
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29839 次 |
| 最近记录: |