简体   繁体   English

如何创建具有“灵活”属性的 C# class?

[英]How to create a C# class with 'flexible' properties?

I'm trying to write a JSON file, which consists in a series of questions, that each have basically the following structure:我正在尝试编写一个 JSON 文件,该文件包含一系列问题,每个问题基本上具有以下结构:

{
        "values": [
            "oui"
        ],
        "question": "h_d",
        "type": "radio",
        "conditions": {
            "lhs": {
                "question": "valeur_wed"
            },
            "operator": "eq",
            "rhs": 0
        },
        "conditionalInfo": []
    },

What I do to produce the JSON file is to have a JSONQuestion class, for which I create a new instance for every question and I provide the different values for the properties.生成 JSON 文件的方法是创建一个JSONQuestion class,为此我为每个问题创建一个新实例,并为属性提供不同的值。 Then I do a JsonSerializer.Serialize(list_of_JSONQuestion_instances) in order to get my JSON text file (using System.Text.Json).然后我执行JsonSerializer.Serialize(list_of_JSONQuestion_instances)以获得我的 JSON 文本文件(使用 System.Text.Json)。

Now, this all works fine, except that the "conditions" element in every question should actually be more flexible.现在,这一切都很好,除了每个问题中的“条件”元素实际上应该更灵活。 For instance, the "lhs" (and/or the "rhs") could itself contain a whole other condition, like this:例如,“lhs”(和/或“rhs”)本身可以包含一个完整的其他条件,如下所示:

{
        "values": [],
        "question": "calcul_wed_rugosite_cp",
        "conditions": {
            "lhs": {
                "lhs": {
                    "question": "valeur_wed"
                },
                "operator": "eq",
                "rhs": "calcule"
            },
            "operator": "and",
            "rhs": {
                "lhs": {
                    "question": "calcul_h_sur_d_script"
                },
                "operator": "eq",
                "rhs": 1
            }
        },

And it could even go deeper, with more levels of lhs and rhs.它甚至可以更深地 go,具有更多的 lhs 和 rhs 级别。 So, the lhs and rhs of each question can be of varying complexity.因此,每个问题的左侧和右侧可能具有不同的复杂性。

My question is therefore: How can I create some sort of Condition class that would have 3 properties ( lhs , rhs , and operator ), but 'flexible'?因此,我的问题是:如何创建某种具有 3 个属性( lhsrhsoperator )但“灵活”的Condition class ? Sometimes the rhs is just a string or an int , but sometimes it's a whole new Condition istelf.有时rhs只是一个string或一个int ,但有时它是一个全新的Condition istelf。 Same for lhs .对于lhs也是如此。

Is it feasible at all?这完全可行吗?

I was thinking using this:我在想用这个:

public class Condition<L, R>
    where L : class
    where R : class
   {
        public L lhs { get; set; }
        public string @operator { get; set; }
        public R rhs { get; set; }
    }

...but then how do I declare the 'conditions' property in my main JSONQuestion class? ...但是如何在我的主要 JSONQuestion class 中声明“条件”属性? As I obviously can't do this:因为我显然不能这样做:

public class JSONQuestion
{
    public string question { get; set; }
    public Condition<L, R> conditions { get; set; }
    ...
}

You could use the [JsonExtensionData] attribute.您可以使用[JsonExtensionData]属性。 It allows you to declare a dictionary-property that you analyze after deserialization to see what it contains.它允许您声明一个字典属性,您可以在反序列化后分析它以查看它包含的内容。 We use it primarily when we need to embed JSON-data inside our own JSON.我们主要在需要将 JSON 数据嵌入到我们自己的 JSON 中时使用它。

If you are using Newtonsoft.JSON:如果您使用的是 Newtonsoft.JSON:
https://www.newtonsoft.com/json/help/html/DeserializeExtensionData.htm https://www.newtonsoft.com/json/help/html/DeserializeExtensionData.htm

If you are using .NET's JSON impl.:如果您使用 .NET 的 JSON 实现:
https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?pivots=dotnet-6-0 https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?pivots=dotnet-6-0

I generally try to avoid custom (de)serialisers so I'm biased towards solutions that don't use them.我通常会尽量避免使用自定义(反)序列化器,所以我偏向于不使用它们的解决方案。

I would have data structure like this:我会有这样的数据结构:

public class Node
{
   public string? Type{ get; set; } // This decide what other values mean
   public string? Value { get; set; }
   public Node Lhs? { get; set; }
   public string? Operator { get; set; }
   public Node? Rhs { get; set; }
}

This is very unsophisticated but allows to represent the trees you shown.这非常简单,但允许表示您显示的树。

The json would be something like this: json 是这样的:

{
    "Type": "Question",
    "Value": "calcul_wed_rugosite_cp",
    "Lhs": {
        "Lhs": {
            "Type": "Question",
            "Value": "valeur_wed"
        },
        "Operator": "eq",
        "Rhs": {
            "Type": "calcule",
            "Value": "I'm not sure how 'calcule' condition works" 
        }
    },
    "Operator": "and",
    "Rhs": {
        "Lhs": {
            "Type": "Questions",
            "Value": "calcul_h_sur_d_script"
        },
        "Operator": "eq",
        "Rhs": {
            "Type": "Value",
            "Value": "1"
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM