【问题标题】:How to set a default value from appsettings to a property on a API Model如何将 appsettings 中的默认值设置为 API 模型上的属性
【发布时间】:2019-10-16 18:09:22
【问题描述】:

如何在由 .NET Core 3 框架实例化的模型上为属性设置默认值,从我的 appsettings.json 文件中读取它?

我创建了一个 repo(一个全新的 .NET Core 3 项目),我试图在其中说明问题:https://github.com/NelsonPRSousa/dependency-injection-default-constructor

API 操作:

[HttpGet]
public IEnumerable<WeatherForecast> Get([FromQuery] FilteringRequestModel request)
{

    var defaultType = request.Type;

    var rng = new Random();
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}

型号:

public class FilteringRequestModel
{
    /* Please note that we must have a parameterless constructor, since it's the framework responsability to instatiate this object
     * when invoking this action: IEnumerable<WeatherForecast> Get([FromQuery] FilteringRequestModel request)
     */

    public FilteringRequestModel()
    {
        //Type = System.Configuration.ConfigurationManager.AppSettings["DefaultTypeTopRated"];
    }

    public string Type { get; set; } = "top_rated"; // TODO: Read from appsettings
}

【问题讨论】:

  • 为什么你的构造函数中的设置被注释掉了?
  • 因为不行所以返回null
  • 不应该。请在实例化类实例的行上放置一个调试点,并在该点检查对象属性。您没有在代码中显示这一点。传递给“Get”方法的对象可能没有设置该属性。所以,从你有 var request = new FilteringRequestModel() 的地方开始,然后在你的调试器中前进。
  • 我没有实例化 FilteringRequestModel。当我们调用 Get 端点时,这项工作是 .NET Core 框架的职责。我这里有所有代码:github.com/NelsonPRSousa/…(只是一个简单的控制器 + 模型)

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


【解决方案1】:

你可以使用 IOptions 和依赖注入

更新FilteringRequestModel

public class FilteringRequestModel
{
    public FilteringRequestModel()
    {
    }

    public void Initialize(IOptions<FilteringRequestSettings> settings)
    {
        if (string.IsNullOrEmpty(this.Type))
        {
            this.Type = settings.Value.Type;
        }
    }

    public string Type { get; set; }
}

添加一个FilteringRequestSettings

public class FilteringRequestSettings
{
    public string Type { get; set; }
}

像这样更新appsettings.Development.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "FilteringRequest": {
    "Type":  "foo"
  }
}

像这样在Startup 类中更新ConfigureServices 方法

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<FilteringRequestSettings>(this.Configuration.GetSection("FilteringRequest"));

    services.AddControllers();
}

最后,像这样更新WeatherForecastController

[HttpGet]
public IEnumerable<WeatherForecast> Get([FromQuery] FilteringRequestModel request)
{
    request.Initialize(_settings);

    var defaultType = request.Type;

    var rng = new Random();
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}

解释

  • 您将从 appsettings 加载参数到 IOptions&lt;FilteringRequestSettings&gt;
  • IOptions&lt;FilteringRequestSettings&gt; 将被注入 WeatherForecastController
  • 然后您将调用Initialize 方法您的request 参数为IOptions&lt;FilteringRequestSettings&gt;
  • Initialize 方法验证是否尚未设置 Type 属性(来自查询/请求)。如果不是,它将使用 appsettings 中的值(通过IOptions&lt;FilteringRequestSettings&gt;

【讨论】:

  • 这是一个很好的解决方法,但是基于这个解决方案,我们没有使用默认的内联初始值(实例化对象时该值为 null)。此外,我们需要在控制器上添加一些逻辑。我期待在无参数构造函数中有一些魔力(比如通过 DI 获得一些依赖,但猜测这是不可能的)。顺便说一句,谢谢你的 fork,它有助于测试它!
  • 作为无参构造函数用于创建模型。您不能使用基于构造函数注入的 .NET Core 默认依赖注入。也许您可以使用另一个 DI 容器,例如 autofac 来使用属性注入?
  • 这是一个解决方案,是的......那么,使用 .NET Core 默认依赖注入是不可能的,是吗?
猜你喜欢
  • 2020-01-14
  • 1970-01-01
  • 2013-09-15
  • 1970-01-01
  • 2012-08-20
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 2010-10-16
相关资源
最近更新 更多