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

时间:2019-06-18 20:20:05

标签: c# asp.net-core dependency-injection asp.net-core-2.1

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

Program.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();
        }
    }
}

Functions.cs

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

appsettings.json

{
  "ConnectionStrings": {
    "MyDatabase": "foo",
    "AzureWebJobsDashboard": "foo2",
    "AzureWebJobsStorage": "foo3"
  }
}

但是,当我运行它时,出现以下错误:

  

错误索引方法“ Functions.ProcessQueueMessage”

     

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

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

1 个答案:

答案 0 :(得分:0)

请考虑更改方法,而不要尝试注入IConfiguration

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

public class MyOptions {
    public string MyDatabase { get; set; }
}

将设置重构为也使用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.AddSingeton(myOptions);
    }
    .ConfigureLogging((context, b) => {
        b.AddConsole();
    });

//...

这样,您现在应该可以将对象添加为函数的依赖项

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

我个人认为,尝试在启动之外访问IConfiguration会比其价值更大的麻烦,甚至会使用服务定位器反模式并注入IServiceProvider对其进行排名。在设置过程中从中获取所需的信息,并在服务集合中进行注册,以便在明确需要时可将其用于注入。