Мне нужно определить тип свойств класса во время выполнения, чтобы я мог выполнить преобразование данных перед назначением. Я видел кучу ответов на 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;
}
Что я делаю неправильно в любом из этих двух подходов?
Привет, Клаус, да, это была проблема. Спасибо.
В вашем классе у вас есть такие свойства, как
public int? Id { get; set; }
Но в вашем коммутаторе вы проверяете этот случай
case Type _ when propertyInfo.PropertyType == typeof(int):
и проблема в том, что typeof(int?) != typeof(int)
Вам нужно добавить случаи для ваших типов, допускающих значение NULL.
Тьфу.... и двойное тьфу... да, это был тот факт, что свойства обнулялись. Спасибо за оперативный ответ - и отличные глаза. :)
Вместо переключателя я бы использовал полное имя типа 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<>
?
@KlausGütter Только для вас - посмотрите propertyInfo.PropertyType.FullName в отладчике, и вы поймете весь код.
Конечно, но это делает предположения о типе, который может произойти. Попробуйте, что произойдет, если вы добавите еще одно свойство List<int> X { get; set; }
@KlausGütter Мне очень жаль, но вам нужно создать всю библиотеку для всех возможных типов. Это выходит за рамки этого поста и SO. ОП опубликовал класс и его код для этого класса, и я предлагаю более компактное решение.
@KlausGütter Но специально для таких людей, как вы, я обновил свой код, теперь вы можете попробовать добавить список. И кстати, что будет, если в код добавить список, который был принят?
У вас нет
case
s дляint?
,double?
иDateTime?
. Два свойстваstring
отлично работают для меня.