簡體   English   中英

ASP.NET Core 中的選項模式 - 如何將子選項作為 JSON 字符串返回(非強類型)

[英]Options Pattern in ASP.NET Core - how to return sub-options as a JSON string (not strongly typed)

以下文檔說明了如何使用 ASP.NET Core 中的選項模式來創建強類型選項類來訪問 JSON 配置數據。

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options

這個 C# 類

public class MyOptions
{
    public string Option1 { get; set; }
    public int Option2 { get; set; }
}

表示此 JSON 配置文件的一部分(前兩個根級屬性)

{
  "option1": "value1_from_json",
  "option2": -1,
  "subOptions": {
    "subOption1": "subvalue1_from_json",
    "subOption2": 200
  }
}

我想將另一個名為SubOptions 的C# 屬性添加到返回subOptions JSON 子部分的原始數據的MyOptions類中,而不為 JSON 配置文件的該子部分創建強類型類,但我不知道要使用什么數據類型(或者甚至可以這樣做)。

如果我使用string ,我會在service.Configure<MyOptions>(Configuration);時收到運行時錯誤service.Configure<MyOptions>(Configuration); 被調用,說System.InvalidOperationException: 'Cannot create instance of type 'System.String' 因為它缺少公共無參數構造函數。

如果我使用objectdynamic ,當service.AddSingleton(cfg => cfg.GetService<IOptions<MyOptions>>().Value);時,我會收到不同的運行時錯誤service.AddSingleton(cfg => cfg.GetService<IOptions<MyOptions>>().Value); 被調用以注冊 MyOptions 類的實例,說System.ArgumentNullException: '值不能為空。 參數名稱:類型'

如果我使用JObject ,當我訪問注入到我的 API 控制器中的 MyOptions 對象的SubOptions屬性時,我會返回{}

我知道我可以通過轉義子部分數據將子部分轉換為 JSON 字符串屬性,但我想避免將子部分視為字符串,而是將其保留為原始 JSON。

可以做我想做的事嗎? 是否有一種與選項模式配合使用的數據類型,它允許我訪問 JSON 子部分而無需創建強類型類?

*作為背景,我正在嘗試創建一個 API 控制器方法,該方法將 JSON 子部分的內容返回給 API 客戶端。 我想避免為子節使用強類型類,以便可以在服務器上編輯 JSON 配置文件,向將返回給 API 客戶端的子節添加新的屬性和值,而無需更新 C# 代碼並重新部署 API 服務。 換句話說,我希望 JSON 子部分是“動態的”,只需將其拉出並發送給客戶端。 *

我想,您可以使用 Newtonsoft.Json 包中的JObject - 它是 Asp.Net Core 中的默認 JSON 解析器和序列化器

您可以通過強制您的 SubOptions 屬性為IConfigurationSection來獲取原始配置對象:

public class MyOptions
{
    public string Option1 { get; set; }
    public int Option2 { get; set; }
    public IConfigurationSection SubOptions { get; set; } // returns the "raw" section now
    public string SubOptions_take2 { get; set; }
}

所以你仍然會在你的 Startup.cs 中綁定你的強類型對象

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration);
    ...
}

但這是運氣似乎用完的地方,因為即使它是一個完整的部分 - 就選項綁定器而言,它已經全部反序列化並解析為值的層次結構。 似乎沒有簡單的方法可以將它重新組合成一根弦。 注入IOptionsMonitor允許您通過選擇.GetChildren()來獲取值,但我找不到一種明顯的方法來獲取整個層次結構,而無需編寫自定義代碼來遞歸遍歷它(如果您願意,我會留下供您使用)覺得這值得努力):

public IndexModel(IOptionsMonitor<MyOptions> options)
{
    _options = options.CurrentValue;

    var subOptions = _options.SubOptions as ConfigurationSection;
    var children = subOptions.GetChildren(); // you see, the config has already been parsed into this hierarchy of items - it's too late to get the raw string value
    var s = JsonConvert.SerializeObject(children);
    // will produce something like this JSON:
    //[{"Path":"SubOptions:subOption1","Key":"subOption1","Value":"subvalue1_from_json"},{"Path":"SubOptions:subOption2","Key":"subOption2","Value":"200"}]    
}

解決它的一種方法是將您的 json 實際編碼為配置文件中的字符串:

"subOptions_take2": "{\"subOption1\": \"subvalue1_from_json\",\"subOption2\": 200}"

然后你可以稍后抓住它:

public IndexModel(IOptionsMonitor<MyOptions> options)
{
    _options = options.CurrentValue;
    var subOptions_string = _options.SubOptions_take2;// this is valid json now: {"subOption1": "subvalue1_from_json","subOption2": 200}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM