您如何在 ASP.NET Core 6 中为 IConfiguration 实现 DI?

How do you implement DI for IConfiguration in ASP.NET Core 6?

我一直在关注 official Microsoft documentation 并且我尝试像下面这样增强我的代码库:

public class GRequestModel(IConfiguration config) => _config = config;
{
    private readonly IConfiguration Configuration;

    public string path { get; set; }
    public string secret { get; set; }
    public string response { get; set; }
    public string remoteip { get; set; }

    public GRequestModel(string res, string remip)
    {
        response = res;
        remoteip = remip;
        var secret = Configuration["GoogleRecaptchaV3:Secret"];
        var path = Configuration["GoogleRecaptchaV3:ApiUrl"];
        if (String.IsNullOrWhiteSpace(secret) || String.IsNullOrWhiteSpace(path))
        {
            //Invoke logger
            throw new Exception(
                "Invalid 'Secret' or 'Path' properties in appsettings.json. " + 
                "Parent: GoogleRecaptchaV3.");
        }
    }
}

但是如果我按照文档中的说明去做,我会不断收到很多错误...

澄清一下 - 我的目标是从 appsettings.json 读取秘密和 API URL 并使用它来设置 Google 的 reCAPTCHA v3 的值。

我需要这样做,因为我想将我的 Web 应用程序迁移到 .NET 6 的稳定版本。

首先,你的语法是错误的。依赖注入应该通过构造函数完成(尽管一些 IoC 容器也提供 属性 注入):

public class GRequestModel
{
    public string path { get; set; }
    public string secret { get; set; }
    public string response { get; set; }
    public string remoteip { get; set; }

    public GRequestModel(IConfiguration configuration, string res, string remip)
    {
        response = res;
        remoteip = remip;
        var secret = configuration["GoogleRecaptchaV3:Secret"];
        var path = configuration["GoogleRecaptchaV3:ApiUrl"];
        if (String.IsNullOrWhiteSpace(secret) || String.IsNullOrWhiteSpace(path))
        {
            //Invoke logger
            throw new Exception("Invalid 'Secret' or 'Path' properties in appsettings.json. Parent: GoogleRecaptchaV3.");
        }
    }
}

现在我们在正确的地方接受 IConfiguration,我们可以解决如何创建这个对象并从容器中获取 IConfiguration。为此,我将在 GRequestModel class:

中创建一个委托
public class GRequestModel
{
    public delegate GRequestModel Factory(string res, string remip);

然后我们可以将这个工厂注册到容器中:

services.AddTransient<GRequestModel.Factory>(serviceProvider => 
     (string res, string remip) => new GRequestModel(serviceProvider.GetRequiredService<IConfiguration>(), res, remip));

现在您可以注入 GRequestModel.Factory 并使用它创建 GRequestModel:

public class SomeOtherClass
{
    public SomeOtherClass(GRequestModel.Factory grequestFactory)
    {
        GRequestModel grm = grequestFactory("resValue", "remipValue");
    }
}

Try it online


编辑:针对您关于它比文档更复杂的评论,这是因为您的用例比文档示例更复杂。具体来说,您要接受参数 resremip.

考虑这个例子:

public class MyService
{
    private readonly IConfiguration _configuration;

    public MyService(IConfiguration configuration)
    {
       _configuration = configuration;
    }

    public void DoSomething(string res, string remip)
    {
        string configValue = _configuration["myConfigKey"];
    }
}

您可以像这样注册并使用它:

services.AddTransient<MyService>();

public class MyOtherClass
{
    public MyOtherClass(MyService service)
    {
        service.DoSomething("resValue", "remipValue");
    }
}

这要简单得多,因为您不需要将参数注入到构造函数中。这真的取决于你想做什么是最好的选择。