[英]Best Way to Retrieve Actual Concrete Object Of a Certain Type From a Json-String in C#?
我目前正在努力確定 json-string 反序列化器在 C# 中返回哪些類型。我試圖制作一個基本 TypeWHATEVER class,其中 TypeX 和 TypeY 從它們繼承,但仍然每當我嘗試檢索實際的 object 與特定類型,它不起作用,因為兩者都可以使用相同的構造函數創建一個新實例。
假設我有 TypeX 和 TypeY。 它們都有相似的構造函數,例如:都有一個帶有參數(字符串a,字符串b)的構造函數。 但是,TypeY 有一個額外的帶參數的構造函數,例如 (string a, string b, string c)。
現在,每當我在 TypeY 中使用額外的構造函數或什至只是類似的構造函數時,它仍然不會產生我想要的結果(它仍然將它視為 TypeX 和 TypeY)......在我不使用的一種方法中知道要返回哪種類型,因為 object 是從 Json-String 反序列化的。 還把 T 和放在提供 object 支持的方法上,但它適用於這兩個類,這不是我想要的......我什至在每個不同的底層 Type 類中放置了一個枚舉,但自從類型也在基 class 中定義。
如何或什么是確定如何從 json 字符串中獲取實際 object 類型的最佳方法,其中有相似的構造函數,但它們仍然彼此不同......
請幫我解決這個問題:(
就像我之前說的,我有一個基礎 class 或接口無關緊要,還有兩個子類
基地 Class:例如 Parent.cs
public class Parent
{
public virtual ClassType Type { get; protected set; } = ClassType.Undefined;//this is an enum and used to differentiate between the different classes. However, this doesn't work, because of the parent type will always be Undefined whenever a child type is converted from json-string to explicit Parent type...
public string Id { get; set; }
public string Message { get; set; }
public Parent()
{
}
public Parent(string id, string message = "")
{
Id = id;
Message = message;
}
}
孩子 Class:例如 ChildA.cs
public class ChildA : Parent
{
public override ClassType Type => ClassType.Default;
public ChildA()
{
}
public ChildA(string id, string message = "") : base(id, message)
{
}
}
孩子 Class:例如 ChildB.cs
public class ChildB : Parent
{
private object testObjectA;
private object testObjectB;
private object testObjectC;
public override ClassType Type => ClassType.New;
public object TestObjectA
{
get { return testObjectA; }
set { testObjectA = value; }
}
public object TestObjectB
{
get { return testObjectB; }
set { testObjectB = value; }
}
public object TestObjectC
{
get { return testObjectC; }
set { testObjectC = value; }
}
public ChildB()
{
}
public ChildB(string id, string message) : base(id, message)
{
}
public ChildB(string id, IDictionary<string, object> collection, string message = "") : this(id, message) // should I use 'this' or 'base' here for id and message, because I already get the base class for the second constructor and it makes sense to me just to take this class since the other is already been using the base class?
{
testObjectA = collection[Constants.A];
testObjectB = collection[Constants.B];
testObjectC = collection[Constants.C];
}
}
Json 轉換器 Class:例如 JsonConverterClass.cs
public static T StringToObject<T>(string json)
=> JsonConvert.DeserializeObject<T>(json);//using Newtonsoft.Json;
現在我有一個 Json 字符串,我想將其轉換為 ChildA 或 ChildB。 Json-String 是這樣的:
{
"type": "New",//This is the ClassType for example
"id": "Some String...",
"message": "",
"collection": {
"objectA": "A",
"objectB": "B",
"objectC": "C",
}
}
讓我們嘗試轉換不起作用的 Json 字符串,並在方法中返回 Child object,不幸的是這不起作用:
public Parent GetObjectExample(string json_String)
{
Parent parentClass = JsonConverterClass.StringToObject<Parent>(json_String);// I don't know how I maybe can use reflection here to accomplish, maybe this is an option too?
switch (parentClass.Type)
{
case ClassType.Default:
parentClass = parentClass as ChildA;
break;
case ClassType.New:
parentClass = parentClass as ChildB;
break;
}
return parentClass;
}
這里的問題是我希望 ChildB 回饋。 但是,由於兩個類具有相同的構造函數。 它無法識別將 ChildB 還給用戶。 事實上,它只是返回一個隨機的 class。ChildA 或 ChilB,在大多數情況下,它只是返回 ChildA 真正奇怪的東西。
希望我能盡可能清楚地告知您正在發生的事情,我真的不知道為什么我的方法不起作用......
好的,我認為有很多事情要評論。 讓我們開始:
在具有 3 個參數的構造函數中,使用this
而不是base
。 想象一下這種情況:
public ChildB(string id, string message)
: base(id, message)
{
this.FullName = $"{id} {message}";
}
public ChildB(string id, IDictionary<string, object> collection, string message = "")
: this(id, message)
{
}
調用this
,你的 3 params 構造函數運行 2 params 構造函數設置FullName
屬性。 如果你使用base
, FullName
將不會被初始化,你必須在你的 3 params 構造函數中復制這一行。
C# 知道任何 object 的類型。實際上,您不需要ClassType
屬性。 您可以執行以下操作:
if (myChildBInstance.GetType() == typeof(ChildB))
我建議您刪除此屬性。
此外,該財產受到保護。 您不能通過序列化更改它的值。 序列化(默認情況下)適用於公共屬性。
我認為,您問題的關鍵在於構造函數。 序列化時,始終使用無參數構造函數。 在反序列化中,調用不帶參數的構造函數,然后設置屬性。
永遠不會使用 JSON 字符串中的Type
屬性。 您無法設置該值,因為它受到保護並且您的實例是在您開始處理這些屬性之前創建的。
var json = @"{
'type': 'New',//This is the ClassType for example
'id': 'Some String...',
'message': '',
'collection': {
'objectA': 'A',
'objectB': 'B',
'objectC': 'C',
}
}";
var obj = StringToObject<ChildB>(json);
當您運行前面的代碼時,會創建ChildB
(因為StringToObject
的T
類型),然后設置所有 JSON 字符串(公共)屬性。 因此,您的類型屬性不可能對選擇 object 的類型有用。 collection
不是您的 object 的屬性:這就是為什么您的 object 沒有獲得這些 A、B、C 值的原因。
使用此示例:
var childB = new ChildB
{
Id = "Id",
Message = "Msg",
TestObjectA = 1,
TestObjectB = 2,
TestObjectC = 3
};
var json = JsonConvert.SerializeObject(childB);
您的 JSON 必須是這樣的:
{
"TestObjectA":1,
"TestObjectB":2,
"TestObjectC":3,
"Id":"Id",
"Message":"Msg"
}
然后,您以這種方式獲得有效的 object:
var obj = StringToObject<ChildB>(json);
如果您要使用不同的類型和 inheritance,那么您必須使用TypeNameHandling = TypeNameHandling.All
。我在鏈接https://stackoverflow.com/a/72270480/18452174之前評論過的所有內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.