如何从 .Net Core 2.1 中的静态函数中访问我的配置?

Mat*_*nks 5 c# dependency-injection asp.net-core asp.net-core-2.1

我正在 .Net Core 2.1 中创建一个 Azure Web 作业(通过 Visual Studio 中的“控制台”应用程序)。在这个项目中,我有一个从队列中读取消息的静态函数。在此函数中,我需要使用连接字符串(来自我的配置)写入数据库。这是我的设置:

程序.cs

class Program
{
    static void Main(string[] args)
    {
        var builder = new HostBuilder();
        builder.ConfigureWebJobs(b =>
        {
            b.AddAzureStorageCoreServices();
            b.AddAzureStorage();
        });
        builder.ConfigureAppConfiguration((hostContext, config) =>
        {
            var conf = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
            config.AddConfiguration(conf);
            config.AddEnvironmentVariables();
        })
        builder.ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        });
        var host = builder.Build();
        using (host)
        {
            host.Run();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

函数.cs

public class Functions
{
    public static void ProcessQueueMessage([QueueTrigger("myqueue")] string message, ILogger logger, IConfiguration configuration)
    {
        logger.LogInformation(message);
        logger.LogInformation(configuration.GetConnectionString("MyDatabase"));
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序设置.json

{
  "ConnectionStrings": {
    "MyDatabase": "foo",
    "AzureWebJobsDashboard": "foo2",
    "AzureWebJobsStorage": "foo3"
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行此命令时,出现以下错误:

索引方法“Functions.ProcessQueueMessage”出错

无法将参数“配置”绑定到类型 IConfiguration。确保绑定支持参数类型。如果您使用绑定扩展(例如 Azure 存储、ServiceBus、计时器等),请确保您已在启动代码中调用扩展的注册方法(例如 builder.AddAzureStorage()、builder.AddServiceBus( )、builder.AddTimers() 等)。

我对 .Net Core 非常陌生,尤其是 DI 模式。我相信这就是问题所在。我还看到了许多如何在函数内部实现和使用配置的示例Main,但不是从像这样的静态辅助函数内部实现和使用配置。如何在静态函数中正确实现配置?

Nko*_*osi 3

考虑改变方法而不是尝试注入IConfiguration

创建一个类来保存您所需的设置

public class MyOptions {
    public string MyDatabase { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

重构设置以使用ConfigureServices和提取所需的配置来填充设置对象并将其添加到服务集合中

var builder = new HostBuilder();
builder
    .ConfigureWebJobs(b => {
        b.AddAzureStorageCoreServices();
        b.AddAzureStorage();
    })
    .ConfigureAppConfiguration(config => { //not using context so no need for it really
        config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
        config.AddEnvironmentVariables();
    })
    //...ADDITION HERE
    .ConfigureServices((context, services) => {
        //Configuration should be available by now, so access what you need.
        var connectionString = context.Configuration.GetConnectionString("MyDatabase");
        //If null you have the option to fail early, otherwise carry on.
        var myOptions = new MyOptions {
            MyDatabase = connectionString,
        };
        services.AddSingleton(myOptions);
    }
    .ConfigureLogging((context, b) => {
        b.AddConsole();
    });

//...
Run Code Online (Sandbox Code Playgroud)

这样,此时您应该能够将对象添加为函数的依赖项

public class Functions {
    public static void ProcessQueueMessage(
        [QueueTrigger("myqueue")] string message, 
        ILogger logger, 
        MyOptions options) {
        logger.LogInformation(message);
        logger.LogInformation(options.MyDatabase);
    }
}
Run Code Online (Sandbox Code Playgroud)

我个人认为尝试IConfiguration在启动之外进行访问比其价值更麻烦,甚至会将其与服务定位器反模式和注入一起排名IServiceProvider。在设置过程中从中获取您需要的内容,将其注册到服务集合中,以便可以在明确需要的地方进行注入。