【问题标题】:Check whether any property within class is null检查类中的任何属性是否为空
【发布时间】:2020-05-12 20:12:56
【问题描述】:

我正在编写一个简单的控制台天气应用程序 (OpenWeatherMap),我想验证来自 OWM 的响应是否包含任何空属性。这是我的包含属性的类:

public class WeatherMain
    {
        public Coord coord { get; set; }
        public List<Weather> weather { get; set; }
        public Main main { get; set; }
        public Wind wind { get; set; }
        public Rain rain { get; set; }
        public Snow snow { get; set; }
        public Clouds clouds { get; set; }
        public Sys sys { get; set; }
        [JsonProperty("base")]
        public string _base { get; set; }
        public int? visibility { get; set; }
        public int? timezone { get; set; }
        public int? id { get; set; }
        public string name { get; set; }
        public int? cod { get; set; }
    }

如您所见,还有一些类也包含它们自己的属性。 我想检查一下,如果这些中的任何一个基本上是空的,那么我可以在控制台中通知缺失值。现在,我使用 IF 对 WeatherMain 属性进行了一些基本检查:

    public static string PrepareResponse(WeatherMain input)
    {
        string cityName, main, visibility, wind, clouds, rain, snow, coord;

        if (input.name == null)
            cityName = "City name section not found\n";
        else
            cityName = $"\nCity name: {input.name}\n";
        if (input.main == null)
            main = "Main section not found\n";
        else
        {
            main = $"Main parameters:\n\tTemperature: {input.main.temp}C\n\t" +
            $"Temperature max.: {input.main.temp_max}C\n\tTemperature min.: {input.main.temp_min}C" +
            $"\n\tFeels like: {input.main.feels_like}C\n\tPressure: {input.main.pressure}hPA\n\t" +
            $"Humidity: {input.main.humidity}%\n";
        }
        if (input.visibility == null)
            visibility = "Visibility section not found\n";
        else
            visibility = $"Visibility: {input.visibility}m\n";
        if (input.wind == null)
            wind = "Wind section not found\n";
        else
            wind = $"Wind:\n\tSpeed: {input.wind.speed}m/s\n\tDirection: {input.wind.deg}deg\n";
        if (input.clouds == null)
            clouds = "Clouds section not found\n";
        else
            clouds = $"Clouds: {input.clouds.all}%\n";
        if (input.rain == null)
            rain = "Rain section not found\n";
        else
            rain = $"Rain: {input.rain._1h}mm\n";
        if (input.snow == null)
            snow = "Snow section not found\n";
        else
            snow = $"Snow: {input.snow._1h}mm\n";
        if (input.coord == null)
            coord = "Coordinates section not found\n";
        else
            coord = $"Coordinates:\n\tLatitude: {input.coord.lat}\n\tLongitude: {input.coord.lon}\n";

        string outputString = cityName + main + visibility + wind + clouds + rain + snow + coord;

        return outputString;
    }

我正在考虑将这些属性放入一个集合中,并一一检查它们是否为空,并可能将值更改为字符串。 我想有更好的方法可以做到这一点。 有什么想法吗?

【问题讨论】:

  • 除非您愿意创建一个 Attribute 来描述每种类型的输出,否则最好的想法可能是创建一个 List,其中包含用于 null 和格式化消息的 lambda,并运行List.

标签: c# json properties null


【解决方案1】:

您可以使用Reflection 命名空间来做到这一点:

        var weather = new WeatherMain
        {
            visibility = 2,
            timezone = 5
        };

        Type t = weather.GetType();
        Console.WriteLine("Type is: {0}", t.Name);
        PropertyInfo[] props = t.GetProperties();
        Console.WriteLine("Properties (N = {0}):",
                          props.Length);
        foreach (var prop in props)
            if (prop.GetValue(weather) == null)
            {
                Console.WriteLine("   {0} ({1}) is null", prop.Name,
                                  prop.PropertyType.Name);
            }

这是一个小提琴示例:https://dotnetfiddle.net/MfV7KD

【讨论】:

    【解决方案2】:

    使用描述符类,您可以将值访问、空消息和格式化输出合并到一个位置,然后循环它们。

    首先,Parameter 类将描述每个参数:

    public class Parameter {
        public Func<WeatherMain, object> Value;
        public string NullName;
        public Func<WeatherMain, string> FormatSection;
    }
    

    然后,static List 将描述您要测试和输出的所有参数:

    public static List<Parameter> Parameters = new[] {
            new Parameter { Value = w => w.name, NullName = "City name", FormatSection = w => $"City name: {w.name}" },
            new Parameter { Value = w => w.main, NullName = "Main",
                            FormatSection = w => $"Main parameters:\n\tTemperature: {w.main.temp}C\n\t" +
                                                 $"Temperature max.: {w.main.temp_max}C\n\tTemperature min.: {w.main.temp_min}C" +
                                                 $"\n\tFeels like: {w.main.feels_like}C\n\tPressure: {w.main.pressure}hPA\n\t" +
                                                 $"Humidity: {w.main.humidity}%" },
    
            new Parameter { Value = w => w.visibility, NullName = "Visibility", FormatSection = w => $"Visibility: {w.visibility}" },
            new Parameter { Value = w => w.wind, NullName = "Wind", FormatSection = w => $"Wind:\n\tSpeed: {w.wind.speed}m/s\n\tDirection: {w.wind.deg}deg" },
            new Parameter { Value = w => w.clouds, NullName = "Clouds", FormatSection = w => $"Clouds: {w.clouds.all}%" },
            new Parameter { Value = w => w.rain, NullName = "Rain", FormatSection = w => $"Rain: {w.rain._1h}mm" },
            new Parameter { Value = w => w.snow, NullName = "Snow", FormatSection = w => $"Snow: {w.snow._1h}mm" },
            new Parameter { Value = w => w.coord, NullName = "Coordinates", FormatSection = w => $"Coordinates:\n\tLatitude: {w.coord.lat}\n\tLongitude: {w.coord.lon}" },
        }.ToList();
    

    最后,您可以通过遍历列表来生成格式化的响应:

    public static string PrepareResponse(WeatherMain input) {
        var ans = new List<string>();
    
        foreach (var p in Parameters) {
            if (p.Value(input) == null)
                ans.Add($"{p.NullName} section not found");
            else
                ans.Add(p.FormatSection(input));
        }
    
        return String.Join("\n", ans);
    }
    

    【讨论】:

    • 像魅力一样工作。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    相关资源
    最近更新 更多