Как работать с конфигурацией в C#, НЕ используя ASP. NET Core? - PullRequest
1 голос
/ 17 июня 2020

Я использую. NET Core 3.1.

Microsoft предлагает подробное руководство о том, как работать с конфигурацией для ASP. NET. Однако я не могу найти руководства по использованию конфигурации в приложении. NET Core, которое не использует ASP. NET.

Как мне получить доступ к файлам конфигурации из C# консольное приложение?

Ответы [ 4 ]

2 голосов
/ 17 июня 2020

Функциональность конфигурации не встроена в. NET Ядро (очевидно). Вам нужно будет ввести его, используя Nuget и некоторую конфигурацию запуска. По сути, вам нужно будет зарегистрировать свою конфигурацию. Вот как ...

Установите пакеты NuGet:

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Microsoft.Extensions.Configuration.CommandLine
Install-Package Microsoft.Extensions.Configuration.EnvironmentVariables 

Добавьте файл appsettings.json в свой проект на уровне root. Вам нужно будет зарегистрировать его так:

static async Task Main(string[] args)
{

  IConfiguration Configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .Build();
}

Теперь, когда ваши провайдеры зарегистрированы в вашем консольном приложении, вы можете ссылаться на свою конфигурацию следующим образом:

var section = Configuration.GetSection("MySectionOfSettings");
var configValue = Configuration.GetValue("MySetting");
2 голосов
/ 17 июня 2020

Между ними нет такой большой разницы.

Теперь я собираюсь предположить, что вы не просто хотите консоль. Записывать значения, но вы в конечном итоге захотите чтобы иметь доступ к ним внутри некоторого реального кода .... ниже используется "UserController" в качестве кода, которому нужен доступ к вашим значениям конфигурации.

Хорошо, главное с do tnet core - это ваша конфигурация INJECT (обычно это класс POCO) (дополнительные параметры см. в разделе IOptions далее в этом ответе) в ваш код, который требует конфигурации. Вы не «берете значение из app.config или web.config», как вы это делали в do tnet framework. Пожалуйста, перечитайте это и используйте его, чтобы изменить свое мышление с do tnet -framework . Я не могу этого достаточно подчеркнуть. Ваш «настоящий код», которому нужны значения конфигурации, не должен go извлекать и читать файл .... вы должны INJECT poco (или IOptions<MyPoco>) в свой класс.

Это типичная настройка, которую я делаю в основном консольном приложении do tnet.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

public static class Program
{
    public static int Main(string[] args)
    {
        try
        {
            /* look at the Project-Properties/Debug(Tab) for this environment variable */
            string environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
            Console.WriteLine(string.Format("DOTNET_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);

            IConfigurationBuilder builder = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json")
                    .AddJsonFile($"appsettings.{environmentName}.json", true, true)
                    .AddEnvironmentVariables();
            /* pay attention to the "true, true" arguments above, they reflect optional: true, reloadOnChange: true ..  "optional" being the important one here */


            IConfigurationRoot myconfig = builder.Build();

            IServiceProvider servicesProvider = BuildDi(myconfig );
            using (servicesProvider as IDisposable)
            {
                /* now do something with your properly composed IoC container */

                /* maybe something like this...*/
                IUserController uc = servicesProvider.GetRequiredService<IUserController>();

                 /* UserController will have the email-config injected into it, because you did the IoC container setup correctly in "BuildDi" method .. later in this answer */

                Console.WriteLine("Press ANY key to exit");
                Console.ReadLine();
            }

================ ============

Итак, что это за строка

.AddJsonFile($"appsettings.{environmentName}.json"

все про?

Там маг c ОКРУЖЕНИЕ переменная для управления вещами.

Одно из немногих мест, где я нашел другое имя. net основные консольные приложения находятся здесь:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.1

Итак, для asp. net основных приложений я установил

ASPNETCORE_ENVIRONMENT 

для do tnet основных консольных приложений, я установил

DOTNET_ENVIRONMENT

==== ========

Таким образом, с указанным выше вы должны иметь как минимум файл «appsettings. json».

Но вы можете опционально иметь эти файлы.

appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json

Вы можете узнать больше об этом здесь: https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/

Теперь, как получить те значения, которые находятся в. json файлах i в ваш код, который в них нуждается.

В do tnet -core конфигурационные poco обычно вводятся в классы.

https://medium.com/@dozieogbo / a-better-way-to -inject-appsettings-in- asp - net -core-96be36ffa22b

Выше показан хороший пример ...

======== ===============

public class EmailConfig {
    public string Username { get; set;}  
    public string Password { get; set;} 
}

=======================

public class UserController : IUserController
{
    private readonly EmailConfig _emailConfig;

    public UserController(EmailConfig emailConfig)
    {
        _emailConfig = emailConfig;

        //_emailConfig.Username
        //_emailConfig.Password
    }
}

и. json будут добавлены с вашим дополнительным настраиваемым разделом / областью конфигурации ... Следуя тому же примеру, ниже показан файл по умолчанию. json ... НО С " Электронная почта »добавлен в.

"ConnectionStrings": {
  "DefaultConnection": ""
},
"Logging": {
  "IncludeScopes": false,
  "LogLevel": {
    "Default": "Warning"
  }
},
"Email": {
  "Username": "peanut",
  "Password": "butter"
}

=======================

====== =================

    private static IServiceProvider BuildDi(IConfiguration myconfig)
    {


        ////setup our DI
        IServiceCollection servColl = new ServiceCollection()
            .AddLogging();  /* do any other stuff here that is extension method */


        EmailConfig emailConfig = new EmailConfig();
        myconfig.GetSection("Email").Bind(emailConfig);
        /* you may want to check for null here on emailConfig */

        //Create singleton from instance..and push to the IoC container
        servColl.AddSingleton<EmailConfig>(emailConfig);

         /* not shown here.. but you'll need to add IUserController,UserController as well */

        ServiceProvider servProv = servColl.BuildServiceProvider();

        return servProv;
    }

и соответствующие значения csproj.

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.*" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.*" />
  </ItemGroup>

Теперь БОНУС-материал

https://medium.com/@kmar.ayush / eli5-ioptions-vs-ioptionssnaphot-vs-ioptionsmonitor-fab1d7e26a75

Или inte rnet search «ioptions vs ioptionssnaphot vs ioptionsmonitor»

Вы также можно настроить конфигурации POCO с помощью одного из указанных выше «Опций». * 108 8 *

IOptions<T>
When using this, the values will always be same for the lifetime of the application. Changing the value of the appsettings file while the application is running will not make any difference to the value when using IOptions. In other words it is in Singleton scope.

IOptionsSnapshot<T>
Using this will always give you the most up to date values in your config file for every request and will remain the same for the during of your request.


IOptionsMonitor<T>
Using the monitor is almost like having real time access to your settings file. Each time you need the value from the config, it will read it and evaluate whatever is there and return that.

................

Одно из преимуществ внедрения объекта конфигурации Poco в ваш «реальный код» .. заключается в том, что для модульных тестов .. EmailConfig можно "закодировать" без резервного копирования файлов .config /.json). Ака, вы можете протестировать свой код без файла json ... и запустить тест полностью в памяти.


Наконец, вот небольшой пример, который показывает, как на самом деле "добраться до" это значение "по умолчанию" "Производство", когда не заданы никакие переменные среды:

    public static class Program
    {
        static void Main(string[] args)
        {

            string environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
            Console.WriteLine(string.Format("DOTNET_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);

            environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            Console.WriteLine(string.Format("ASPNETCORE_ENVIRONMENT='{0}'", environmentName));
            Console.WriteLine(string.Empty);


            /* both empty strings above */

            Microsoft.Extensions.Hosting.HostBuilder builder = new Microsoft.Extensions.Hosting.HostBuilder();
            builder
            .ConfigureHostConfiguration(config =>
            {
                config.AddEnvironmentVariables(prefix: "DOTNETCORE_");
            })
             .ConfigureAppConfiguration((context, config) =>
             {
                 config.AddJsonFile("appsettings.json", optional: true);
                 config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
             });


            Microsoft.Extensions.Hosting.IHost hst = builder.Build();

            /* do NOT do the below in real code..this is cheap trick to show EnvironmentName default */
            Microsoft.Extensions.Hosting.IHostEnvironment env = hst.Services.GetService(typeof(Microsoft.Extensions.Hosting.IHostEnvironment)) as Microsoft.Extensions.Hosting.IHostEnvironment;
            if (null != env)
            {
                Console.WriteLine(env.EnvironmentName);
            }
}

и соответствующие части csproj

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.*" />
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.*" />

  </ItemGroup>

Вывод:

DOTNET_ENVIRONMENT=''

ASPNETCORE_ENVIRONMENT=''

Production
1 голос
/ 17 июня 2020

Какой у вас мог бы appsettings.json файл. Затем у вас может быть класс для представления этого файла, например:

public class Settings
{
    public string ConnectionString { get; set; }
}

Затем в методе main вы можете прочитать свой Json файл и десериализовать его, используя System.Text.Json, в нужный вам класс , например:

using (var fs = File.OpenRead(fileName))
{
    var settings = JsonSerializer.Deserialize<Settings>(fs);
    // set this in a accessible variable
}
0 голосов
/ 17 июня 2020

У нас есть собственная подсистема конфигурации, которая ищет набор файлов конфигурации И может использовать реестр для перенаправления на конкретную конфигурацию c. Ничто не мешает вам написать собственную подсистему конфигурации - первая версия заняла около 4 часов работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...