光看標題的確不好說明問題,下面描述一下問題場景:
已知後端自定義的返回的Json數據結構如下:
response:
{
"message": "返回成功",
"result":
[
{
"name":"AAA",
"age":16
},
{
"name":"BBB",
"age":17
}
],
"state": 1
}
顯然,根據Json的結構,客戶端可以自定義一個類來描述請求的相應結果。
public class Response<T>
{
public string message { get; set; }
public ObservableCollection<T> result { get; set; }
public int state { get; set; }
}
其中response.result內容是一個數組。爲了通用性使用泛型T來描述數組中元素的類型(即用T來表示相應的實體類)。如本例中的元素類型描述爲Student類。
public class Student
{
public string name{ get; set; }
public int age{ get; set; }
}
現在,如果返回的Response類型爲Student,而Student類中又包含了一個存儲其他類型的List列表,即Student實體類變成了如下:
response:
{
"message": "返回成功",
"result":
[
{
"name":"AAA",
"list":
[
{
...
},
{
...
}
]
"age":16
},
{
"name":"BBB",
"list":
[
{
...
},
{
...
}
]
"age":17
}
],
"state": 1
}
那麼對應的Student實體類就要新增一個List列表,變成如下:
public class Student
{
public string name{ get; set; }
public int age{ get; set; }
public ObservableCollection<Achievement> list { set; get; } // 假設業務邏輯是實體類是學生的成績
}
問題:
- 如果後臺返回的數據,是一組T類型的數組,而該T類型中又包含了一個S類型的列表,該如何訪問該列表?
- 換句話說,如何訪問泛型類型中的列表?
下面的例子演示如何訪問泛型中的列表數據,並用一個新的引用來保存該列表的數據。爲了通用性,使用了泛型和反射。
public class MyClass
{
public ObservableCollection<Achievement> AchievementList; // 用於記錄Student中的List列表的內容
/// <summary>
/// response.result只有唯一元素,獲取該元素中的【唯一】列表數據
/// </summary>
/// <typeparam name="T">唯一元素的類型</typeparam>
/// <typeparam name="S">唯一元素中的指定列表屬性中,保存的實體類類型</typeparam>
/// <param name="proName">本類中保存返回的唯一元素的列表的引用</param>
/// <param name="listName">元素中的【唯一】列表的屬性名,看實體類</param>
/// <param name="callback ">如果有回調,就在完成數據獲取後執行該回調</param>
public void GetListDataInResult<T, S>(string proName, string listName, Action callback = null) where T : class
{
// 在調用該方法之前,已經獲得了Response數據!
// 獲得response.result中的數據
T item = response.result[0]; // response.result是個數組,但裏面只有一個Student元素
// 反射出該元素的實體類,即本例中的Student類
Type t = item.GetType();
// 獲得該元素中的List列表數據
PropertyInfo listPropertyInfo = t.GetProperty(listName);
ObservableCollection<S> sourceList = (ObservableCollection<S>)listPropertyInfo.GetValue(response.result[0], null); // 本文的重點
// 給本類中的保存該列表的引用賦值
PropertyInfo list = this.GetType().GetProperty(proName);
list.SetValue(this, sourceList);
// 如果有回調,就在完成數據獲取後執行該回調
callback?.Invoke();
}
}
調用上面的方法:
GetListDataInResult<Student, Achievement>("AchievementList", "list", null);