Использование класса Startup в консольном приложении ASP.NET5

Возможно ли использовать консольное приложение ASP.NET 5-beta4 (построенное из шаблона проекта ASP.NET Console в VS2015) для использования класса 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);
  }
}

Я попытался вручную создать класс Startup в моем методе Main, но это не похоже на правильное решение и до сих пор не позволяло мне настраивать службы.

Я предполагаю, что у меня есть способ создать HostingContext, который не запускает веб-сервер, но сохранит консольное приложение. Что-то вроде:

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

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

Однако пока единственный способ заставить это работать - установить HostingContext.ServerFactoryLocation на Microsoft.AspNet.Server.WebListener, который запустит веб-сервер.

Ответы

Ответ 1

То, что вы ищете, - это правильная идея, но я думаю, вам нужно сделать резервную копию.

Во-первых, вы, возможно, заметили, что ваш класс по умолчанию Program больше не использует статические методы; это потому, что конструктор на самом деле получает любовь от зависимостей от инъекций самостоятельно!

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

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

К сожалению, не так много служб, с которыми вы привыкли, из зарегистрированной среды хостинга ASP.NET 5; благодаря этой статье и IServiceManifest вы можете видеть, что доступно только несколько доступных сервисов:

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.

Здесь есть еще несколько "gotchas", поэтому я мог бы также перечислить их:

  • Если вы запрашиваете IHostingEnvironment, он будет равен нулю. Это связано с хостинговой средой, а именно с хостингом ASP.Net 5.
  • Поскольку у вас нет одного из них, вы останетесь без вашего IHostingEnvironment.EnvironmentName - вам нужно будет самостоятельно его собирать из переменных среды. Что, поскольку вы уже загружаете его в свой объект Configuration, не должно быть проблемой. (Это имя "ASPNET_ENV", которое вы можете добавить на вкладку "Отладка" ваших параметров проекта, это не задано для вас по умолчанию для консольных приложений. Возможно, вы захотите переименовать это, так или иначе, больше говоря об среде ASPNET.)