Получение типа свойства класса С#

Мне нужно определить тип свойств класса во время выполнения, чтобы я мог выполнить преобразование данных перед назначением. Я видел кучу ответов на SO, например:

Использование PropertyInfo для определения типа свойства

Но очевидно, что я делаю что-то не так, потому что следующий тестовый код всегда возвращается к случаю по умолчанию:

public class MyClass
{
    public int? Id { get; set; }
    public string Seller { get; set; }
    public DateTime? PaymentDate { get; set; }
    public double? PaymentAmount { get; set; }
    public string PaymentMethod { get; set; }
}....

И тестовый код.

string s = "";
PropertyInfo[] propertyInfos = typeof(MyClass).GetProperties();
...
    foreach (PropertyInfo propertyInfo in propertyInfos)
    {
        switch (propertyInfo.PropertyType)
        {
            case Type _ when propertyInfo.PropertyType == typeof(string):
                    s = "It's a string!";
                break;
            case Type _ when propertyInfo.PropertyType == typeof(int):
                    s = "It's an int!";
                break;
            case Type _ when propertyInfo.PropertyType == typeof(double):
                    s = "It's a double!";
                break;
            case Type _ when propertyInfo.PropertyType == typeof(DateTime):
                s = "It's a datetime!";
                break;
            default:
                ...
                break;
        }
    }
...

Для идентификатора, продавца и т. д. возвращается свойствоInfo, но в переключателе ничего не совпадает. Мне просто нужно определить тип каждого свойства в классе.

Я также пытался использовать TypeCode, но тоже не повезло, поскольку переменная tc всегда имеет значение объекта, не знаю почему:

Type pt = propertyInfo.PropertyType;
TypeCode tc = Type.GetTypeCode( pt );

switch (tc)
{
    case TypeCode.DateTime:
        s = "DateTime";
        break;
    case TypeCode.Int32:
        s = "Int";
        break;
    case TypeCode.String:
        s = "String";
        break;
    default:
        s = "string";
        break;
}

Что я делаю неправильно в любом из этих двух подходов?

У вас нет cases для int?, double? и DateTime?. Два свойства string отлично работают для меня.

Klaus Gütter 22.03.2022 18:41

Привет, Клаус, да, это была проблема. Спасибо.

BarnumBailey 22.03.2022 19:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашем классе у вас есть такие свойства, как

public int? Id { get; set; }

Но в вашем коммутаторе вы проверяете этот случай

case Type _ when propertyInfo.PropertyType == typeof(int):

и проблема в том, что typeof(int?) != typeof(int)

Вам нужно добавить случаи для ваших типов, допускающих значение NULL.

Тьфу.... и двойное тьфу... да, это был тот факт, что свойства обнулялись. Спасибо за оперативный ответ - и отличные глаза. :)

BarnumBailey 22.03.2022 19:30

Вместо переключателя я бы использовал полное имя типа propertyInfo. Используя простые строковые функции, я мог бы извлечь гораздо больше информации о каждом типе свойств.

     PropertyInfo[] propertyInfos = typeof(MyClass).GetProperties();

    foreach (PropertyInfo propertyInfo in propertyInfos)
    {
        var typeName = propertyInfo.PropertyType.FullName;
        var startIndex = typeName.IndexOf("[[");

        if (startIndex > 0)
        {
            var startString = typeName.Substring(startIndex + 9);
            typeName =   typeName.Substring(0,startIndex-2) + " " + startString.Substring(0, startString.IndexOf(","));
        }
        else typeName = typeName.Substring(7);
        
        Console.WriteLine($"{ propertyInfo.Name}  - { typeName}  ");
    }

результат

Id  - System.Nullable Int32  
Seller  - String  
PaymentDate  - System.Nullable DateTime  
PaymentAmount  - System.Nullable Double  
PaymentMethod  - String  
X  - System.Collections.Generic.List Int32  

Можете ли вы объяснить все эти волшебные части в вашем ответе, такие как "[[", startIndex + 9, "," и 7?. Как поведет себя решение, если встречается любой универсальный тип, отличный от Nullabe<>?

Klaus Gütter 22.03.2022 19:54

@KlausGütter Только для вас - посмотрите propertyInfo.PropertyType.FullName в отладчике, и вы поймете весь код.

Serge 22.03.2022 19:55

Конечно, но это делает предположения о типе, который может произойти. Попробуйте, что произойдет, если вы добавите еще одно свойство List<int> X { get; set; }

Klaus Gütter 22.03.2022 20:00

@KlausGütter Мне очень жаль, но вам нужно создать всю библиотеку для всех возможных типов. Это выходит за рамки этого поста и SO. ОП опубликовал класс и его код для этого класса, и я предлагаю более компактное решение.

Serge 22.03.2022 20:03

@KlausGütter Но специально для таких людей, как вы, я обновил свой код, теперь вы можете попробовать добавить список. И кстати, что будет, если в код добавить список, который был принят?

Serge 22.03.2022 20:12

Другие вопросы по теме