2014-02-19 174 views
1

我有這樣定義這個簡單的模型類:我有這個網頁API,返回CountryLanguage的IEnumerable存儲結果

public class CountryLanguage 
{ 
    public string Name { get; set; } 
    public string ShortName { get; set; } 
    public string Description { get; set; } 
} 

[HttpGet] 
public IEnumerable<CountryLanguage> Get() 
{   
    List<CountryLanguage> list = new List<CountryLanguage>(); 
    list.Add(new CountryLanguage()); 
    list.Add(new CountryLanguage()); 
    return list; 
} 

我有這個類,我想存儲Web API調用的結果:

public class ResponseResult<T> 
{ 
    public HttpStatusCode StatusCode { get; set; } 
    public string Message { get; set; } 
    public T Payload { get; set; } 
} 

最後,我在這裏是代碼調用Web API:

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, actionToCallWithParameters); 

var response = httpClient.SendAsync(request).Result; 

ResponseResult<T> responseResult = new ResponseResult<T>(); 
responseResult.StatusCode = response.StatusCode; 
responseResult.Message = response.Content.ReadAsStringAsync().Result; 
responseResult.Payload = response.Content.ReadAsAsync<T>().Result;     

return responseResult; 

如果Web API返回CountryLanguage對象,我得到這個存儲對象到我的泛型類型物業的有效載荷沒有問題。

但如果Web API返回一個IEnumerable,我得到這個錯誤:

不能反序列化JSON當前陣列(例如[1,2,3])轉換成式「CountryLanguage」,因爲類型要求JSON對象(例如{\「name \」:\「value \」})來正確反序列化。要修復這個錯誤,可以將JSON更改爲JSON對象(例如{\「name \」:\「value \」})或將反序列化類型更改爲數組或實現集合接口的類型(例如ICollection,IList)像List,可以從JSON數組中反序列化。 JsonArrayAttribute也可以添加到類型中,以強制它從JSON數組反序列化。

我的問題是:是否有可能「正常化」此代碼,所以我可以存儲一個對象或IEnumerable到我的有效載荷屬性的T型?

回答

0

好了,就可以到IEnumerable存儲到泛型類型T.

的變量,如果我希望返回的數據是一個對象,調用我需要做的是:

ResponseResult<CountryLanguage> response = serviceConnector.GetData <CountryLanguage>(actionToCall); 

如果我期待的IEnumerable從呼叫:

ResponseResult<IEnumerable<CountryLanguage>> response = 
       serviceConnector.GetData<IEnumerable<CountryLanguage>>(actionToCall); 

所以我的錯誤是一個事實,即調用代碼時,我並沒有指定IEnumerable的類型。

0

其實你的邏輯不正確。如果在運行時你的T類型是'CountryLanguage'類型,那麼你的Payload屬性就像CountryLanguage屬性一樣。這就是爲什麼當您嘗試將IEnumerable值分配給屬性時會引發錯誤,因爲您將IEnumerable對象分配給非可枚舉屬性。
基本上,在運行時,該系統是這樣做的:

CountryLanguage Payload = IEnumerable<CountryLanguage>(variable); 

這顯然會拋出一個錯誤。

+0

是的你是對的。但是,您能想出任何可以將對象或IEnumerable的結果存儲到一個泛型類型變量中的方法嗎? – Elferone

+0

是的,如果您使用「對象」類型聲明有效載荷,則可以在其中存儲任何內容。但是拆開它以後再使用會遇到很多麻煩。如果我是你,我會將Payload設置爲列表列表。然後,我會讓服務總是返回一個List 對象,即使只填充了一個索引。 – LcSalazar

1

有了這個改變,我能夠解決這個問題,但我不認爲它完全回答你的問題。我會在下面給出你的答案的解決方案,但這裏是我添加的解決運行時問題的方法,它會返回你的列表。

var responseResult = new ResponseResult<IEnumerable<CountryLanguage>> 
{ 
    StatusCode = response.StatusCode, 
    Message = response.Content.ReadAsStringAsync().Result, 
    Payload = response.Content.ReadAsAsync<IEnumerable<CountryLanguage>>().Result 
}; 

基本上只是把你的T變成了IEnumerable如果T類或方法,那麼你可以將其設置爲IEnumerable的定義爲CountryLanguage但您的代碼不顯示完整的類或方法。

現在到您的其他問題,從一個通用方法返回對象或對象列表。第一個反應是正確的,你只需要返回對象和box/unbox,並使用反射和其他非常不愉快的代碼,這些代碼可能被封裝,但仍然有點麻煩。因此,如果您的目標是將此返回的有效內容用於CountryLanguage以外的其他內容,則可以嘗試以下操作。創建一個名爲PayloadWrapperthat新類包含兩個屬性,像這樣:

public class PayloadWrapper<T> 
{ 
    public T Item { get; set; } 
    public IEnumerable<T> Items { get; set; } 
} 

然後你可以設置或其他在你的WebAPI,並在其上設置客戶端檢查。

public PayloadWrapper<CountryLanguage> Get() 
{ 
    var languages = new List<CountryLanguage> {new CountryLanguage(), new CountryLanguage()}; 

    var payload = new PayloadWrapper<CountryLanguage>(); 
    payload.Items = languages; 
    payload.Item = null; 
    return payload; 
} 

和客戶端上:

var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:34213/api/values/"); 
var httpClient = new HttpClient(); 
var response = httpClient.SendAsync(request).Result; 

    var responseResult = new ResponseResult<PayloadWrapper<CountryLanguage>> 
    { 
     StatusCode = response.StatusCode, 
     Message = response.Content.ReadAsStringAsync().Result, 
     Payload = response.Content.ReadAsAsync<PayloadWrapper<CountryLanguage>>().Result 
    }; 

你的有效載荷現在是一個單一的對象,要麼包含一個項目或同一項目的列表。可用於發回符合此模式的任何內容。