首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从开放天气地图API获取天气数据

从开放天气地图API获取天气数据
EN

Code Review用户
提问于 2016-12-27 21:13:01
回答 2查看 19.1K关注 0票数 7

我正试图在C#中制作一个简单的应用程序,从http://openweathermap.org/api (OWM)获取天气数据。

下面是两个类,用于初始化所选城市的WeatherData,以及从OWM API下载和解析XML数据。我想知道你对这些类的结构和我使用它们的方式的看法,因为现在我真的不知道如果我想在将来获得/打印更多的天气数据,它应该如何工作。

我使用它们如下:

代码语言:javascript
复制
WeatherData WarsawWeather = new WeatherData("Warsaw");
WarsawWeather.CheckWeather();
System.Console.WriteLine(WarsawWeather.Temp);

课程:

代码语言:javascript
复制
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:

代码语言:javascript
复制
<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>
EN

回答 2

Code Review用户

发布于 2016-12-27 21:41:05

不需要为属性显式声明备份字段

私有字符串城市;公共字符串城市{获取{返回城市;} set { City = value;}

你可以把它缩短到这样:

代码语言:javascript
复制
public string City { get; set; }

您应该尽可能限制您的属性,并删除不必要的属性。

代码语言:javascript
复制
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 &&同名的私有类变量这样的参数之间的混淆,可以为私有类变量添加下划线:

代码语言:javascript
复制
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,这意味着您只能从构造函数中给它一个值。

票数 3
EN

Code Review用户

发布于 2016-12-28 11:35:30

我认为你的职责分工有点不对。例如,为什么要将WeatherApi的每个实例绑定到特定的位置?在我看来,最好晚些时候把这个地点传过去。该名称也与实现过于相关。调用方不必担心数据来自API。

该类的另一个问题是在构造函数中做一些重要的工作。一般来说,初始化对象应该很便宜。我建议您将其拆分,以便用户创建一个WeatherRepository,然后调用一个GetWeatherData方法来实际执行请求。

代码语言:javascript
复制
var weatherRepository = new WeatherRepository();
var warsawData = weatherRepository.GetWeatherData("warsaw");
Console.WriteLine(warsawData.CurrentTemperature);

注意,我还让GetWeatherData返回您的WeatherData类,而不是填充XmlDocument。大概是这样的:

代码语言:javascript
复制
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方法可能就像使用XmlSerializerDataContractSerializer直接反序列化数据一样简单。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/150981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档