我正试图在C#中制作一个简单的应用程序,从http://openweathermap.org/api (OWM)获取天气数据。
下面是两个类,用于初始化所选城市的WeatherData,以及从OWM API下载和解析XML数据。我想知道你对这些类的结构和我使用它们的方式的看法,因为现在我真的不知道如果我想在将来获得/打印更多的天气数据,它应该如何工作。
我使用它们如下:
WeatherData WarsawWeather = new WeatherData("Warsaw");
WarsawWeather.CheckWeather();
System.Console.WriteLine(WarsawWeather.Temp);课程:
using System.Net;
using System.Xml;
namespace WeatherApp
{
class WeatherData
{
public WeatherData(string City)
{
city = City;
}
private string city;
private float temp;
private float tempMax;
private float tempMin;
public void CheckWeather()
{
WeatherAPI DataAPI = new WeatherAPI(City);
temp = DataAPI.GetTemp();
}
public string City { get => city; set => city = value; }
public float Temp { get => temp; set => temp = value; }
public float TempMax { get => tempMax; set => tempMax = value; }
public float TempMin { get => tempMin; set => tempMin = value; }
}
class WeatherAPI
{
public WeatherAPI(string city)
{
SetCurrentURL(city);
xmlDocument = GetXML(CurrentURL);
}
public float GetTemp()
{
XmlNode temp_node = xmlDocument.SelectSingleNode("//temperature");
XmlAttribute temp_value = temp_node.Attributes["value"];
string temp_string = temp_value.Value;
return float.Parse(temp_string);
}
private const string APIKEY = "API KEY HERE";
private string CurrentURL;
private XmlDocument xmlDocument;
private void SetCurrentURL(string location)
{
CurrentURL = "http://api.openweathermap.org/data/2.5/weather?q="
+ location + "&mode=xml&units=metric&APPID=" + APIKEY;
}
private XmlDocument GetXML(string CurrentURL)
{
using (WebClient client = new WebClient())
{
string xmlContent = client.DownloadString(CurrentURL);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlContent);
return xmlDocument;
}
}
}
}来自OWM的示例XML:
<current>
<city id="756135" name="Warsaw">
<coord lon="21.01" lat="52.23"/>
<country>PL</country>
<sun rise="2016-12-27T06:45:16" set="2016-12-27T14:30:06"/>
</city>
<temperature value="2" min="2" max="2" unit="metric"/>
<humidity value="80" unit="%"/>
<pressure value="1019" unit="hPa"/>
<wind>
<speed value="6.7" name="Moderate breeze"/>
<gusts/>
<direction value="310" code="NW" name="Northwest"/>
</wind>
<clouds value="40" name="scattered clouds"/>
<visibility value="10000"/>
<precipitation mode="no"/>
<weather number="802" value="scattered clouds" icon="03n"/>
<lastupdate value="2016-12-27T20:00:00"/>
</current>发布于 2016-12-27 21:41:05
不需要为属性显式声明备份字段
私有字符串城市;公共字符串城市{获取{返回城市;} set { City = value;}
你可以把它缩短到这样:
public string City { get; set; }您应该尽可能限制您的属性,并删除不必要的属性。
public string City { get; }
public float Temp { get; private set; }这些是您使用的惟一的两个属性,其他属性是冗余的,正如您可以看到的,我已经向您的属性添加了一些额外的修饰符,现在City是一个readonly属性,而Temp只有一个private设置器
类成员和参数之间存在一些冲突。
私有XmlDocument GetXML(string CurrentURL) { using (WebClient client = new WebClient()) { string xmlContent = client.DownloadString(currentURL);xmlDocument XmlDocument =新XmlDocument();xmlDocument.LoadXml(xmlContent);返回xmlDocument;}
您已经有了名为xmlDocument && CurrentURL的变量--这可能会导致一些奇怪的行为,您应该更改它们的名称。
您的命名不一致:
私有字符串CurrentURL;私有XmlDocument xmlDocument;
这两个变量都是私有的,但其中一个变量以大写字母开头,通常只有公共成员遵循Pascal案例类型,它们都应该遵循Camel案例类型。
您的参数也是如此:
公共WeatherData(string City) { this.City = City;} public WeatherAPI(string city) {SetCurrentURL(城市);_xmlDocument = GetXML(_currentURL);}
2个公共构造函数,其中一个具有Pascal案例类型的参数,另一个是遵循Camel案例类型的参数,因为它们都是参数,因此它们都应该遵循Camel case类型。
为了避免像currentURL &&同名的私有类变量这样的参数之间的混淆,可以为私有类变量添加下划线:
private string _currentURL;
private readonly XmlDocument _xmlDocument;
private XmlDocument GetXML(string currentURL)
{
using (WebClient client = new WebClient())
{
string xmlContent = client.DownloadString(currentURL);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlContent);
return xmlDocument;
}
}注意,_xmlDocument也被标记为readonly,这意味着您只能从构造函数中给它一个值。
发布于 2016-12-28 11:35:30
我认为你的职责分工有点不对。例如,为什么要将WeatherApi的每个实例绑定到特定的位置?在我看来,最好晚些时候把这个地点传过去。该名称也与实现过于相关。调用方不必担心数据来自API。
该类的另一个问题是在构造函数中做一些重要的工作。一般来说,初始化对象应该很便宜。我建议您将其拆分,以便用户创建一个WeatherRepository,然后调用一个GetWeatherData方法来实际执行请求。
var weatherRepository = new WeatherRepository();
var warsawData = weatherRepository.GetWeatherData("warsaw");
Console.WriteLine(warsawData.CurrentTemperature);注意,我还让GetWeatherData返回您的WeatherData类,而不是填充XmlDocument。大概是这样的:
public WeatherData GetWeatherData(string location)
{
var endpoint = GetUrlForLocation(location);
var xmlData = GetXmlFrom(endpoint);
// todo: implement this.
return CreateDataFromXml(xmlDocument);
}
private XmlDocument GetXmlFrom(string endpoint)
{
using (var webClient = new WebClient())
{
var xmlContent = webClient.DownloadString(endpoint);
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlContent);
return xmlDocument;
}
}如果创建类来匹配xml或添加适当的元数据,CreateDataFromXml方法可能就像使用XmlSerializer或DataContractSerializer直接反序列化数据一样简单。
https://codereview.stackexchange.com/questions/150981
复制相似问题