C# 如何将appsettings.json文件添加到my Azure Function 3.0配置中?

C# 如何将appsettings.json文件添加到my Azure Function 3.0配置中?,c#,azure,dependency-injection,configuration,azure-functions,C#,Azure,Dependency Injection,Configuration,Azure Functions,新的Azure Function 3.0 SDK提供了一种实现启动类的方法。它允许访问依赖注入提供的服务集合,我可以在其中添加自己的组件和第三方服务 但我不知道如何使用配置文件 [assembly: FunctionsStartup(typeof(MyNamespace.Startup))] namespace MyNamespace { public class Startup : FunctionsStartup { public override void

新的Azure Function 3.0 SDK提供了一种实现启动类的方法。它允许访问依赖注入提供的服务集合,我可以在其中添加自己的组件和第三方服务

但我不知道如何使用配置文件

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
...
我的第三方服务以大型结构为参数,这些配置文件是用二进制文件复制的。我可以在appsettings.json文件的子部分中复制它们:

配置值将根据部署环境进行更新。我使用Azure Devops的文件转换任务来实现这一点:生产值不同于临时值和开发值

根据文档,加载这些选项的方法是:

builder.Services.AddOptions<MachineLearningConfig>()
                .Configure<IConfiguration>((settings, configuration) =>
                                           {
                                                configuration.GetSection("MachineLearningConfig").Bind(settings);
                                           });
builder.Services.AddOptions()
.Configure((设置、配置)=>
{
configuration.GetSection(“MachineLearningConfig”).Bind(设置);
});
但这需要将所有设置添加为主机环境中的key/value字符串,而这正是我不想做的。它们太多了,维护起来不像json配置文件那么容易

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
...
我将appsettings.json与host.json一起复制

但是Azure Function SDK在启动时读取的appsettings.json文件不是我的应用程序的appsettings.json,而是Azure Function tools的appsettings.json。因此
configuration.GetSection(“MachineLearningConfig”)
返回空值,因为Azure Function tools bin文件夹中没有appsettings.json文件


因此,我的问题是:如何让我的
MachineLearningConfig
部分从我的
appsetting.json
文件中读取,并在我的应用程序中作为
IOption
注入?

在本地开发函数应用程序时,必须在
local.settings.json
项目文件中维护这些值的本地副本。要了解更多信息,请参阅文件

将所需设置上载到Azure中的功能应用程序的最简单方法是使用成功发布项目后显示的管理链接

有关如何获取这些设置值的信息,请参阅本节

var config = new ConfigurationBuilder()
                .SetBasePath(currentDirectory)
                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();
下面是startup类中的一个

    IConfigurationRoot config = new ConfigurationBuilder()
              .SetBasePath(Environment.CurrentDirectory)
              .AddJsonFile("someSettings.json", optional: true, reloadOnChange: true)
              .AddEnvironmentVariables()
              .Build();
public class Startup : FunctionsStartup
{
    private IConfigurationRoot _functionConfig = null;

    private IConfigurationRoot FunctionConfig( string appDir ) => 
        _functionConfig ??= new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(appDir, "appsettings.json"), optional: true, reloadOnChange: true)
            .Build();

    public override void Configure(IFunctionsHostBuilder builder)
    {
         builder.Services.AddOptions<MachineLearningSettings>()
             .Configure<IOptions<ExecutionContextOptions>>((mlSettings, exeContext) =>
                 FunctionConfig(exeContext.Value.AppDirectory).GetSection("MachineLearningSettings").Bind(mlSettings) );
    }
}

将一个json文件添加到包含设置的项目中。请注意,在部署过程中会忽略/删除local.settings.json。(将文件命名为其他名称。)

经过一些研究,我在Githib上发现了这个线程

根据这些评论和建议,我精心设计了以下扩展,这些评论和建议显示了它们的有效性

public static class FunctionHostBuilderExtensions {
    /// <summary>
    /// Set up the configuration for the builder itself. This replaces the 
    /// currently registered configuration with additional custom configuration.
    /// This can be called multiple times and the results will be additive.
    /// </summary>
    public static IFunctionsHostBuilder ConfigureHostConfiguration (
        this IFunctionsHostBuilder builder, 
        Action<IServiceProvider, IConfigurationBuilder> configureDelegate) {
        IServiceCollection services = builder.Services;            
        var providers = new List<IConfigurationProvider>();            
        //Cache all current configuration provider
        foreach (var descriptor in services.Where(d => d.ServiceType == typeof(IConfiguration)).ToList()) {
            var existingConfiguration = descriptor.ImplementationInstance as IConfigurationRoot;
            if (existingConfiguration is null) {
                continue;
            }
            providers.AddRange(existingConfiguration.Providers);
            services.Remove(descriptor);
        }
        //add new configuration based on original and newly added configuration
        services.AddSingleton<IConfiguration>(sp => {
            var configurationBuilder = new ConfigurationBuilder();                    
            //call custom configuration
            configureDelegate?.Invoke(sp, configurationBuilder);                
            providers.AddRange(configurationBuilder.Build().Providers);                
            return new ConfigurationRoot(providers);
        });            
        return builder;
    }
}

以上内容现在应该能够从您的自定义配置中获取设置。

Nkosi的解决方案工作得很好,但它确实通过替换IConfiguration singleton:
services.AddSingleton
更新了azure函数运行时为自己加载设置的方式

我更喜欢使用另一个未注入的IConfigurationRoot。我只需要插入链接到我自己的IConfigurationRoot的设置
IOption

我构建了另一个IConfigurationRoot,它是Startup类的成员:

    IConfigurationRoot config = new ConfigurationBuilder()
              .SetBasePath(Environment.CurrentDirectory)
              .AddJsonFile("someSettings.json", optional: true, reloadOnChange: true)
              .AddEnvironmentVariables()
              .Build();
public class Startup : FunctionsStartup
{
    private IConfigurationRoot _functionConfig = null;

    private IConfigurationRoot FunctionConfig( string appDir ) => 
        _functionConfig ??= new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(appDir, "appsettings.json"), optional: true, reloadOnChange: true)
            .Build();

    public override void Configure(IFunctionsHostBuilder builder)
    {
         builder.Services.AddOptions<MachineLearningSettings>()
             .Configure<IOptions<ExecutionContextOptions>>((mlSettings, exeContext) =>
                 FunctionConfig(exeContext.Value.AppDirectory).GetSection("MachineLearningSettings").Bind(mlSettings) );
    }
}
公共类启动:函数启动
{
私有IConfigurationRoot\u functionConfig=null;
私有IConfigurationRootFunctionConfig(字符串appDir)=>
_functionConfig???=new ConfigurationBuilder()
.AddJsonFile(Path.Combine(appDir,“appsettings.json”),可选:true,重载更改:true)
.Build();
公共覆盖无效配置(IFunctionsHostBuilder)
{
builder.Services.AddOptions()
.Configure((mlSettings,exeContext)=>
FunctionConfig(exeContext.Value.AppDirectory).GetSection(“MachineLearningSettings”).Bind(mlSettings));
}
}

注意:连接字符串必须保留在应用程序设置中,因为触发器需要它来创建未启动的功能应用程序实例(在消费服务计划中)。

使用此.NET Core 3.1Azure function 3。每天花了几个小时。这是我想到的

[assembly: FunctionsStartup(typeof(Ugly.AzureFunctions.Startup))]

namespace Ugly.AzureFunctions
{
    class Startup : FunctionsStartup
    {
        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
        {
            try
            {
                // On Azure, we need to get where the app is.
                // If you use Directory.GetCurrentDirectory(), you will get something like D:\Program Files (x86)\SiteExtensions\Functions\3.0.14785\32bit
                var basePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..");
                var environmentName = builder.GetContext().EnvironmentName;
                builder.ConfigurationBuilder
                    .SetBasePath(basePath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
                    .AddEnvironmentVariables();
            }
            catch (Exception ex)
            {
                // Handle exceptions about this. Which __should__ never ever happen.
                // The previous comment is sarcastic.
                throw;
            }
        }

        public override void Configure(IFunctionsHostBuilder builder)
        {
            try
            {
                // DO NOT add the configuration as Singleton.
                // If you need the IConfiguration:
                //var configuration = builder.GetContext().Configuration;

                builder.Services
                    .AddOptions<MachineLearningConfig>()
                    .Configure<IConfiguration>((settings, configuration) => {
                        configuration.GetSection("MachineLearningConfig").Bind(settings);
                });
            }
            catch (Exception ex)
            {
                // Handle or not handle? That's the question.
                throw;
            }
        }
    }
}
[程序集:函数启动(typeof(ught.AzureFunctions.Startup))]
namespace.AzureFunctions
{
类启动:函数启动
{
公共覆盖无效配置AppConfiguration(IFunctionsConfigurationBuilder)
{
尝试
{
//在Azure上,我们需要了解应用程序的位置。
//如果使用Directory.GetCurrentDirectory(),您将获得类似于D:\Program Files(x86)\SiteExtensions\Functions\3.0.14785\32位的内容
var basePath=Path.Combine(Path.GetDirectoryName(Assembly.getExecutionGassembly().Location),“.”;
var environmentName=builder.GetContext().environmentName;
builder.ConfigurationBuilder
.SetBasePath(基本路径)
.AddJsonFile(“appsettings.json”,可选:true,重载更改:true)
.AddJsonFile($“appsettings.{environmentName}.json”,可选:true,重载更改:true)
.AddenEnvironmentVariables();
}
捕获(例外情况除外)
{
//处理与此相关的异常。这永远不会发生。
//前面的评论是讽刺的。
投掷;
}
}
公共覆盖无效配置(IFunctionsHostBuilder)
{
尝试
{
//不要将配置添加为单例。
//如果需要IConfiguration:
//var configuration=builder.GetContext().configuration;
建筑商服务
.AddOptions()
.Configure((设置、配置)=>{
配置