【问题标题】:UWP object reference required from non-static method非静态方法所需的 UWP 对象引用
【发布时间】:2018-02-22 02:13:23
【问题描述】:

我正在创建一个 UWP 应用程序,简单地说,我有一个异步 void GetWeather 函数,它从 API 读取 JSON 并创建一个对象。调用 Forecast.getWeather() 函数我得到错误“非静态方法所需的对象引用”。我已经完成了我的研究,但还没有找到使用 void 方法的解决方案,因为我还不想返回一个对象。此外,如果这是不可能的(也许是一个更好的主意)我将如何返回 Object 以便它可以在整个应用程序的许多不同页面上使用,或者如果在 void 方法中创建对象值仍然可以访问?

Forecast.cs

    class Forecast
{
    public async void GetWeather()
    {
        var uri = new Uri("MY API URI HERE");
        using (HttpClient client = new HttpClient())
        {
            using (HttpResponseMessage response = await client.GetAsync(uri))
            {
                using (IHttpContent content = response.Content)
                {
                     var json = await content.ReadAsStringAsync();

                    var result = JsonConvert.DeserializeObject<RootObject>(json);
                    Debug.WriteLine("In async method");
                }
            }
        }
    }
}

主页

 public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        Forecast.GetWeather();

    }
}

天气.cs

namespace WeatherForecast
{

public class Main
{
    public double temp { get; set; }
    public double temp_min { get; set; }
    public double temp_max { get; set; }
    public double pressure { get; set; }
    public double sea_level { get; set; }
    public double grnd_level { get; set; }
    public int humidity { get; set; }
    public double temp_kf { get; set; }
}

public class Weather
{
    public int id { get; set; }
    public string main { get; set; }
    public string description { get; set; }
    public string icon { get; set; }
}

public class Clouds
{
    public int all { get; set; }
}

public class Wind
{
    public double speed { get; set; }
    public double deg { get; set; }
}

public class Snow
{
    public double __invalid_name__3h { get; set; }
}

public class Sys
{
    public string pod { get; set; }
}

public class List
{
    public int dt { get; set; }
    public Main main { get; set; }
    public List<Weather> weather { get; set; }
    public Clouds clouds { get; set; }
    public Wind wind { get; set; }
    public Snow snow { get; set; }
    public Sys sys { get; set; }
    public string dt_txt { get; set; }
}

public class Coord
{
    public double lat { get; set; }
    public double lon { get; set; }
}

public class City
{
    public int id { get; set; }
    public string name { get; set; }
    public Coord coord { get; set; }
    public string country { get; set; }
}

public class RootObject
{
    public string cod { get; set; }
    public double message { get; set; }
    public int cnt { get; set; }
    public List<List> list { get; set; }
    public City city { get; set; }
}
}

【问题讨论】:

  • 感谢@John 的快速响应,但这在) 上给出了一个错误,即新表达式在类型后需要 ()、[] 或 {}
  • 哎呀错字。 (new Forecast()).GetWeather();
  • 非常感谢,这极大地拯救了我,而且由于我是 UWP 的新手,我在 forecast.cs 中创建的 result 对象是否可以在我的应用程序的不同页面上使用,或者是预测的范围。 cs ?

标签: c# json http asynchronous uwp


【解决方案1】:

问题是你的方法不是静态的,所以你需要创建一个Forecast类的实例来访问它。您可以在SO questionhere 中阅读更多相关信息。

快速的解决方案也是使您的 Forecast 类静态(只要您不想拥有多个不同的实例):

static class Forecast
{
    public static async void GetWeather()
    {
        var uri = new Uri("MY API URI HERE");
        using (HttpClient client = new HttpClient())
        {
            using (HttpResponseMessage response = await client.GetAsync(uri))
            {
                using (IHttpContent content = response.Content)
                {
                     var json = await content.ReadAsStringAsync();

                    var result = JsonConvert.DeserializeObject<RootObject>(json);
                    Debug.WriteLine("In async method");
                }
            }
        }
    }
}

但是现在我们遇到了一个更大的问题。你的方法是asyncasync void。只有在绝对必要时才应该这样做,因为async void 方法是所谓的即发即弃。它们开始了,但是当它们到达第一个真正的 asynchronous 调用时,它们将自行执行,如果方法内部发生了一些不好的事情(如异常),在症状开始出现之前你永远不会知道它以难以调试的方式在其他地方。此外,您永远不知道result 何时真正可供您使用。

最好的解决方案是Task 返回类型。这代表了一个promise,当方法执行完成时结果将可用。

static class Forecast
{
    public static RootObject Result {get; private set;}

    public static async Task GetWeatherAsync()
    {
        var uri = new Uri("MY API URI HERE");
        using (HttpClient client = new HttpClient())
        {
            using (HttpResponseMessage response = await client.GetAsync(uri))
            {
                using (IHttpContent content = response.Content)
                {
                    var json = await content.ReadAsStringAsync();

                    Result = JsonConvert.DeserializeObject<RootObject>(json);

                    Debug.WriteLine("In async method");
                }
            }
        }
    }
}

您可以看到该方法不再是void,但它仍然没有直接返回RootObject(根据您的要求,否则您可以使用Task&lt;RootObject&gt; 来返回它)。我还添加了一个Result 属性,以便在执行完成时可以访问结果。因为类是static,所以在GetWeatherAsync 方法调用完成后,可以从任何地方访问该属性。

现在如何使用它?您可以在 OnNavigatedTo 处理程序中调用方法,而不是构造函数:

public override async void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo( e );
    try
    {
       await Forecast.GetWeatherAsync();
       //after await finishes, Result is ready

       //do something with Forecast.Result
    }
    catch
    {
       //handle any exceptions
    }
}

你可能注意到我违反了async 方法不应该是void 的规则。但是,在这种情况下,我们正在处理具有固定符号的事件处理程序,因此您别无选择。但是,我添加了一个 try-catch 块,以便我们可以处理任何发生的异常。

我建议在documentation 中阅读更多关于async-await 的内容,因为它会帮助您更好地理解这个概念。我还建议您查看有关实例与静态的更详细信息,以更好地了解它们的区别以及何时使用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多