2014-01-17 58 views
1

我有这样的代码,如果坏的结果遇到在例外的情况下返回null:我该如何重构此代码以不返回null两次?

private JArray GetRESTData(string uri) 
{ 
    try 
    { 
     var webRequest = (HttpWebRequest)WebRequest.Create(uri); 
     var webResponse = (HttpWebResponse)webRequest.GetResponse(); 
     if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0)) 
     { 
      var reader = new StreamReader(webResponse.GetResponseStream()); 
      string s = reader.ReadToEnd(); 
      return JsonConvert.DeserializeObject<JArray>(s); 
     } 
     MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode)); 
     return null; 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
     return null; 
    } 
} 

...但它闻起来有点腐臭。有没有办法我可以重构这个不调用“返回null”两次?

+2

添加最终块返回null那里,从删除这两个尝试和catch块 – Miller

+1

不使用“使用块”任何理由webResponse.GetResponseStream()当你有一个不好的连接时,它会处理这个对象。 – ACS

+2

这段代码有比两个'return null'更大的问题。它吃任意的异常,它将错误显示代码与业务逻辑混合在一起,它不会处理它的资源。在查看琐事之前解决大问题。 –

回答

4

我建议你不要在这个函数中处理异常,假设它的行为正确。

private JArray GetRESTData(string uri) 
{ 
    var webRequest = (HttpWebRequest)WebRequest.Create(uri); 
    var webResponse = (HttpWebResponse)webRequest.GetResponse(); 

    var reader = new StreamReader(webResponse.GetResponseStream()); 
    string s = reader.ReadToEnd(); 

    return JsonConvert.DeserializeObject<JArray>(s); 
} 

我删除了StatusCode检查,因为HttpWebResponse类都已经抛出一个异常,如果它不是一个有效的状态代码。

该方法的责任应该是获取其余数据,而不是处理用户交互(MessageBox)。

为了进一步重构,我将使另一种方法来进行网络请求,另一种方法来解析响应。

private JArray GetRESTData(string uri) 
{ 
    var json = ReadFromUri(uri); 

    return JsonConvert.DeserializeObject<JArray>(json); 
} 

private string ReadFromUri(string uri) 
{ 
    using (var webRequest = (HttpWebRequest)WebRequest.Create(uri)) 
    using (var webResponse = (HttpWebResponse)webRequest.GetResponse()) 
    using (var reader = new StreamReader(webResponse.GetResponseStream())) 
    { 
     return reader.ReadToEnd(); 
    } 
} 

要使用此方法:

try 
{ 
    var myArray = GetRESTData("http://someservice.com/bananabread"); 
} 
catch (WebException exception) 
{ 
    MessageBox.Show("Some exception happened: {0}", exception); 
} 
2

就移动回了try/catch块的

try 
{ 
    var webRequest = (HttpWebRequest)WebRequest.Create(uri); 
    var webResponse = (HttpWebResponse)webRequest.GetResponse(); 
    if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0)) 
    { 
     var reader = new StreamReader(webResponse.GetResponseStream()); 
     string s = reader.ReadToEnd(); 
     return JsonConvert.DeserializeObject<JArray>(s); 
    } 
    MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));  
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 

} 
return null; 
2

我喜欢喜欢一个返回点,如果可能的话

private JArray GetRESTData(string uri) 
{ 
    JArray ret = null; // single return value, declared outside of try/catch 
    try 
    { 
     var webRequest = (HttpWebRequest)WebRequest.Create(uri); 
     var webResponse = (HttpWebResponse)webRequest.GetResponse(); 
     if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0)) 
     { 
      var reader = new StreamReader(webResponse.GetResponseStream()); 
      string s = reader.ReadToEnd(); 
      ret = JsonConvert.DeserializeObject<JArray>(s); 
     } 
     MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode)); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
    return ret; 
} 

注:在这个简单的例子,这大概就够了。在更复杂的功能中,如果已经构建但处于无效状态,则可能需要在异常处理程序内将ret设置为null。但是,如果您使用RAII,这应该不是真正的问题。