чтение appsettings.json в приложении State Service Fabric Fabric - PullRequest
0 голосов
/ 22 июня 2019

Я создал проект API ядра 2.1 для asp.net (не внутри сервисной фабрики), так как, если я добавлю этот код в ValuesController.cs, я смогу получить конфигурацию из appsettings.json

    private IConfiguration configuration;

    public ValuesController(IConfiguration iConfig)
    {
        configuration = iConfig;
    }
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        string dbConn = configuration.GetSection("MySettings").GetSection("DbConnection").Value;
        return new string[] { "value1", "value2" };
    }

Тот же самый аналогичный проект, который я создаю, не требующий состояния проект структуры ядра API-интерфейса asp.net, он не работает по умолчанию. Я должен добавить конкретную ссылку на appsetting.json.Когда я смотрю на проект, они оба выглядят очень похоже.Это правильный подход?такое не требуется в некоммерческом проекте.

return new WebHostBuilder()
                                    .UseKestrel()
                                    .ConfigureAppConfiguration((builderContext, config) =>
                                        {
                                            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                                        })
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseUrls(url)
                                    .Build();

1 Ответ

1 голос
/ 24 июня 2019

Inside Service Fabric Я вообще не использую appsetings. Я придерживаюсь подхода, в котором все параметры всех служб хранятся в одном месте, а именно ApplicationPackageRoot / ApplicationManifest.xml внутри проекта Service Fabric. Так, например, если у меня есть две службы, ApplicationManifest может выглядеть так:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="TestAppType" 
ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Environment" DefaultValue="" />
    <Parameter Name="TestWebApi_InstanceCount" DefaultValue="" />
    <Parameter Name="TestServiceName" DefaultValue="TestService" />
    <Parameter Name="TestService_InstanceCount" DefaultValue="" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="TestServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides>
      <ConfigOverride Name="Config">
        <Settings>
          <Section Name="General">
            <Parameter Name="Environment" Value="[Environment]" />
            <Parameter Name="TestServiceName" Value="[TestServiceName]" />
          </Section>
        </Settings>
      </ConfigOverride>
    </ConfigOverrides>
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="TestWebApiPkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides>
      <ConfigOverride Name="Config">
        <Settings>
          <Section Name="General">
            <Parameter Name="Environment" Value="[Environment]" />
          </Section>
        </Settings>
      </ConfigOverride>
    </ConfigOverrides>
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="TestService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="TestServiceType" InstanceCount="[TestService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="TestWebApi" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="TestWebApiType" InstanceCount="[TestWebApi_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

Я просто поместил там определения параметров, используемых для приложения, и конкретные настройки для каждого сервиса. Следующим шагом является подготовка файлов параметров приложения для каждой среды, в которую вы помещаете реальные значения, например Dev.xml:

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/TestApp" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Environment" Value="Dev" />
    <Parameter Name="TestWebApi_InstanceCount" Value="1" />
    <Parameter Name="TestServiceName" Value="TestService" />
    <Parameter Name="TestService_InstanceCount" Value="-1" />
  </Parameters>
</Application>

Во время развертывания приложения вы просто указываете, какой файл вы хотите использовать. Теперь, чтобы использовать config внутри сервиса, вам нужно изменить файл PackageRoot / Config / Settings.xml для каждого сервиса:

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Section Name="General">
    <Parameter Name="Environment" Value=""/>
    <Parameter Name="TestServiceName" Value=""/>
  </Section>
</Settings>

Опять же, вы не указываете здесь значения, они будут взяты из ApplicationManifest. Вы просто указываете, какой из них вы хотите использовать для конкретной услуги.

Теперь код. Я создал вспомогательный класс для получения значений конфигурации:

public class ConfigSettings : IConfigSettings
{
    public ConfigSettings(StatelessServiceContext context)
    {
        context.CodePackageActivationContext.ConfigurationPackageModifiedEvent += this.CodePackageActivationContext_ConfigurationPackageModifiedEvent;
        UpdateConfigSettings(context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings);
    }

    private void CodePackageActivationContext_ConfigurationPackageModifiedEvent(object sender, PackageModifiedEventArgs<ConfigurationPackage> e)
    {
        this.UpdateConfigSettings(e.NewPackage.Settings);
    }

    public string Environment { get; private set; }
    public string TestServiceName { get; private set; }

    private void UpdateConfigSettings(ConfigurationSettings settings)
    {
        var generalSectionParams = settings.Sections["General"].Parameters;
        Environment = generalSectionParams["Environment"].Value;
        TestServiceName = generalSectionParams["TestServiceName"].Value;
    }
}

public interface IConfigSettings
{
    string Environment { get; }
    string TestServiceName { get; }
}

Этот класс также имеет подписку на событие, которая будет обновлять конфигурацию, если она была изменена во время работы службы.

Осталось инициализировать ConfigSettings контекстом службы во время запуска и добавить его во встроенный контейнер ASP.NET CORE, чтобы вы могли использовать его в других классах:

.ConfigureServices(services => services
    .AddSingleton<IConfigSettings>(new ConfigSettings(serviceContext)))

EDIT:

Если у вас есть свой конфиг в основном контейнере IoC asp.net, вы можете использовать его путем внедрения конструктора следующим образом:

public class TestClass
{
    private readonly IConfigSettings _config;

    public TestClass(IConfigSettings config)
    {
        _config = config;
    }

    public string TestMethod()
    {
        return _config.TestServiceName;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...