Как мне получить доступ к свойству класса из переменной в C #?

#c# #asp.net-core

#c# #asp.net-ядро

Вопрос:

Я создал несколько классов для моделирования данных JSON, возвращаемых из API. Раздел с релевантностью выглядит следующим образом:

 public class ErrorClass
    {
        public string status { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string? unknown_properties { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string? invalid_coordinates { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string? location_error { get; set; }
    }
  

Некоторые из этих свойств ошибки будут отображаться только тогда, когда в моделируемом JSON присутствует ошибка (нулевые значения игнорируются). Я хочу настроить помощника для обработки ошибок. Это проверит, были ли заполнены определенные значения в объекте, и добавит их в сообщения об ошибках соответственно. У меня есть список имен свойств, потенциально принадлежащих объекту класса. Я хочу перебрать список строк и проверить, имеют ли они значение в текущем объекте. Моя проблема в том, что я не уверен, как сделать что-то вроде:

     public class ErrorsHelper
    {
        string[] badRequestErrors = {"invalid_coordinates", "location_error"};
        public void Process_Errors(dynamic errors)
        {
            for (int i = 0; i < badRequestErrors.Length; i  )
            {
                var badRequestError = badRequestErrors[i];
                if (errors.badRequestError[i])
                {
                    // Add to list, etc.
                }
            }
        }
    }
  

Потому что компилятор ищет свойство имени переменной вместо значения этой переменной. Как я могу искать имя свойства в объекте C # таким образом?

Заранее благодарю вас!

Комментарии:

1. Я бы использовал JObject вместо десериализации в класс.

Ответ №1:

Используя отражение, это вернет все свойства JsonPropertyAttribute , аннотированные с.

 var properties = typeof(ErrorClass)
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.GetCustomAttribute<JsonPropertyAttribute>() != null)
                .ToList();
  

Вы можете получить доступ к их именам следующим образом:

 foreach (var propertyInfo in properties)
            {
                Console.WriteLine(propertyInfo.Name);
            }
  

Вы можете получить их значение с помощью:

 var propertyValue = propertyInfo.GetValue(obj);
  

Комментарии:

1. Я пробовал такой подход. Проблема, с которой я столкнулся, заключается в том, что класс, который входит в typeof() , может меняться. Я должен был упомянуть об этом. Он используется для множества разных конечных точек, у которых разные классы ошибок.

2. Затем вы должны использовать .GetType() или typeof(T) , если у вас есть универсальный метод.

3. Проблема в том, что если я попытаюсь использовать .GetType() , а затем передать эту переменную в typeof() , я получу сообщение об ошибке: errorType' is a variable but is used like a type

4. .GetType() дает вам тип. Затем вы можете вызвать .GetProperties его.

Ответ №2:

Высокоуровневый ответ заключается в том, что вы бы использовали reflection . смотрите: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection

Рефлексия часто не рекомендуется, но это правильный подход. См.:

https://softwareengineering.stackexchange.com/questions/143205/reflection-is-using-reflection-still-bad-or-slow-what-has-changed-with-ref

Для некоторого обсуждения. Пара моментов: обычно он «медленнее» (хотя часто не практически) и может обходить проверки компилятора (возможно, приводящие к ошибкам).

Если какая-либо из ваших ошибок достаточно «плохая», чтобы остановить весь процесс, вы также можете yield return использовать средство проверки ошибок и просто проверить все различные типы ошибок в serial, при условии, что типов ошибок не слишком много.

Ответ №3:

Вы можете получить свойства класса, используя приведенный ниже код:

 PropertyInfo[] propertyInfos = typeof(ErrorClass).GetProperties();
        
Array.ForEach(propertyInfos, property => 
Console.WriteLine("Property Name is :"   property.Name));
  

Ответ №4:

Я так и не нашел решения этой проблемы. Проблема заключалась в том, что .getType() возвращалось только class type object значение, и поэтому выполнение предоставленных решений на нем давало бы только available свойства, а не те, которые на самом деле были ненулевыми в объекте.