【问题标题】:C# ConsoleApp injection startup?C# ConsoleApp 注入启动?
【发布时间】:2022-01-17 23:16:18
【问题描述】:

我有一个简单的 C# .NET Core 5 控制台应用程序,我需要将依赖注入 (Microsoft.Extensions.DependencyInjection) 添加到该应用程序。如果它想启动一个微服务,我知道该怎么做,但是如果我只想用 DI 作为常规控制台应用程序运行它怎么办?

我得到了这个代码:

static void Main(string[] args)
{
    var serviceName =
        System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

    var configurationBuilder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json").Build();
    var appSettings = configurationBuilder.Get<AppSettings>();

        Log.Information("{@serviceName} test starting up.", serviceName);
        Host.CreateDefaultBuilder(args)
            .UseMyAppMQ(context => context.UseSettings(appSettings.MQSettings))
            .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
            .ConfigureServices((hostContext, services) =>
            {
                services
                    .Configure<MQSettings>(configurationBuilder.GetSection("MQSettings"))
                    .AddTransient<ITestController>(s => new TestController());
            })
            .Build().Run();

        Log.Information("{@serviceName} test closing down.", serviceName);
}

我需要一个入口点,我可以在其中运行我的底层类 run 方法,但是如何?

问候

【问题讨论】:

  • 这个已经在worker模板中提供了,实际上需要的代码要少得多。运行dotnet new worker 并检查代码。这将创建一个控制台应用程序,该应用程序启动所有已注册的BackgroundService 派生类。如果您想在其中一项服务结束时终止应用程序,您必须通过注入 IHostApplicationLifetime 并调用 StopApplication() 来告诉主机
  • 用它的接口注入你的类(即:.AddTransient();)。然后使用中间件调用你的类运行方法(即:app.Use())。看到这个:docs.microsoft.com/en-us/dotnet/core/extensions/… 和这个:docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/…
  • 否则不用调用Run(),直接用Build()获取主机即可。向主机明确请求“服务”,调用其方法并在完成后退出应用程序。

标签: c# dependency-injection


【解决方案1】:

你需要实现IHostedService接口(或扩展BackgroundService基类)并注册到services.AddHostedService&lt;YourServiceClass&gt;()builder.Services.AddHostedService&lt;YourServiceClass&gt;(),如果使用 .NET 6 最小 API,如 in official docs 所述。在这种情况下,IHostedService.StartAsync 将是您的入口点。

但是,如果您只需要一个带有 DI 的简单控制台应用程序,它似乎效率非常低。正如@Panagiotis Kanavos 建议的那样,您可以在不运行主机的情况下构建主机,因为这样您就可以将其用作 DI 容器的包装器并解析任何已注册的服务。在这种情况下,代码的入口点是构建主机后的下一行,您可以在其中解析任何已注册的依赖项

var host = Host.CreateDefaultBuilder(args)
   ...
   .Build();
host.Services.GetService<YouService>()

但是对于一个控制台应用来说,它仍然是一个低效的解决方案,因为你只需要 DI 容器,而不是整个主机。只需使用任何第三方 DI 框架(如 Autofac、Ninject 或任何其他)而不是 Microsoft.Extensions.DependencyInjection。他们的设置通常是quite minimalistic,你只会得到带有服务的 DI 容器,而没有其他任何东西。您仍然可以使用配置包和记录器,只需将它们注册到您的容器中,就像您之前使用 UseXxxx 方法一样。

【讨论】:

  • 谢谢,在这种情况下我使用 Autofac。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 2020-04-02
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-07
  • 2016-06-13
相关资源
最近更新 更多