【问题标题】:Using Startup class in ASP.NET5 Console Application在 ASP.NET5 控制台应用程序中使用启动类
【发布时间】:2015-05-15 10:53:18
【问题描述】:

ASP.NET 5-beta4 控制台应用程序(基于 VS2015 中的 ASP.NET 控制台项目模板构建)是否可以使用 Startup 类来处理注册服务和设置配置详细信息?

我尝试创建一个典型的 Startup 类,但在通过 dnx . run 或在 Visual Studio 2015 中运行控制台应用程序时似乎从未调用它。

Startup.cs 差不多:

public class Startup
{
  public Startup(IHostingEnvironment env)
  {
    Configuration configuration = new Configuration();
    configuration.AddJsonFile("config.json");
    configuration.AddJsonFile("config.{env.EnvironmentName.ToLower()}.json", optional: true);
    configuration.AddEnvironmentVariables();

    this.Configuration = configuration;
  }

  public void ConfigureServices(IServiceCollection services)
  {
    services.Configure<Settings>(Configuration.GetSubKey("Settings"));

    services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationContext>(options => options.UseSqlServer(this.Configuration["Data:DefaultConnection:ConnectionString"]));
  }

  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  {
    loggerFactory.AddConsole(minLevel: LogLevel.Warning);
  }
}

我尝试在我的Main 方法中手动创建Startup 类,但这似乎不是正确的解决方案,并且到目前为止还不允许我配置服务。

我假设我有某种方法可以创建一个HostingContext,它不会启动 Web 服务器,但会保持控制台应用程序处于活动状态。大致如下:

HostingContext context = new HostingContext()
{
  ApplicationName = "AppName"
};

using (new HostingEngine().Start(context))
{
  // console code
}

但到目前为止,我可以让它工作的唯一方法是将HostingContext.ServerFactoryLocation 设置为Microsoft.AspNet.Server.WebListener,这会启动网络服务器。

【问题讨论】:

  • 是否有 ASP.NET 5 控制台应用程序之类的东西?确定它是 ASP.NET Core 应用程序,还是 .NET Core 控制台应用程序?

标签: c# asp.net-core asp.net-core-mvc


【解决方案1】:

您正在寻找的是正确的想法,但我认为您需要稍等片刻。

首先,您可能已经注意到您的默认Program 类不再使用静态方法;这是因为构造函数实际上获得了一些依赖注入的爱!

public class Program
{
    public Program(IApplicationEnvironment env)
    {            
    }        

    public void Main(string[] args)
    {
    }
}

不幸的是,注册的 ASP.NET 5 托管环境中没有那么多您习惯使用的服务。感谢this articleIServiceManifest,您可以看到只有少数服务可用:

Microsoft.Framework.Runtime.IAssemblyLoaderContainer Microsoft.Framework.Runtime.IAssemblyLoadContextAccessor Microsoft.Framework.Runtime.IApplicationEnvironment Microsoft.Framework.Runtime.IFileMonitor Microsoft.Framework.Runtime.IFileWatcher Microsoft.Framework.Runtime.ILibraryManager Microsoft.Framework.Runtime.ICompilerOptionsProvider Microsoft.Framework.Runtime.IApplicationShutdown

这意味着您也将获得创建自己的服务提供者的乐趣,因为我们无法获得框架提供的服务提供者。

private readonly IServiceProvider serviceProvider;

public Program(IApplicationEnvironment env, IServiceManifest serviceManifest)
{
    var services = new ServiceCollection();
    ConfigureServices(services);
    serviceProvider = services.BuildServiceProvider();
}

private void ConfigureServices(IServiceCollection services)
{
}

这消除了您在标准 ASP.NET 5 项目中看到的许多魔力,现在您可以在 Main 中找到您想要的服务提供商。

这里还有一些“陷阱”,所以我不妨把它们列出来:

  • 如果您要求IHostingEnvironment,它将为空。那是因为托管环境来自 ASP.Net 5 托管。
  • 由于您没有其中之一,因此您将没有IHostingEnvironment.EnvironmentName - 您需要自己从环境变量中收集它。哪一个,因为您已经将它加载到您的配置对象中,所以应该不是问题。 (它的名称是“ASPNET_ENV”,您可以在项目设置的“调试”选项卡中添加它;默认情况下,这不是为您设置的控制台应用程序。无论如何,您可能想要重命名它,因为您不是真的不再谈论 ASPNET 环境了。)

【讨论】:

  • 感谢您的帮助,正如您所指出的,一旦创建了 ServiceProvider,我就可以将其传递给 DbContext。将ServiceProvider 设为静态是否安全?我假设它无法像在 ASP.NET5 托管项目中那样自动附加。
  • 一旦你使用你的IServiceProvider创建了一些东西,它可以通过DI获取IServiceProvider的一个实例,并传播自己。拥有单例服务提供者通常被认为是不好的做法;一开始它就破坏了可测试性。
  • 我使用ServiceProvider 创建了一个DbContext,如果我使用提供程序创建上下文它可以工作,但是当我创建第二个DbContext 而不传递提供程序时它会失败.是否有一些地方我需要手动注册ServiceProvider 才能自动访问它?
  • 一些命名空间发生了变化,但这里还是一样。要在控制台应用程序中指定您自己的服务,就我所知,您需要构建自己的 IServiceProvider,如第二个代码块中给出的那样。 (如果您明确访问它,您甚至可以使用 Startup 类来构建它!)
  • 自 RC1 以来,Main 再次是静态的:github.com/aspnet/Announcements/issues/113
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 2010-10-30
  • 2021-07-19
  • 2017-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多