Как проверить, является ли тип примитивным
у меня есть блок кода, который выполняет в тег html.
Type t = typeof(T); // I pass <T> in as a paramter, where myObj is of type T
tagBuilder.Attributes.Add("class", t.Name);
foreach (PropertyInfo prop in t.GetProperties())
{
object propValue = prop.GetValue(myObj, null);
string stringValue = propValue != null ? propValue.ToString() : String.Empty;
tagBuilder.Attributes.Add(prop.Name, stringValue);
}
это отлично работает, за исключением того, что я хочу, чтобы это делалось только для примитивных типов, таких как int,double,bool etc и другие типы, которые не являются примитивными, но могут быть легко сериализованы, как string. Я хочу, чтобы он игнорировал все остальное, как списки и другие пользовательские типы.
может кто-нибудь подсказать, как я делаю это? Или мне нужно указать типы, которые я хочу разрешить где-то и включить тип свойства, чтобы увидеть, если это разрешено? Это немного грязно, так что было бы неплохо, если бы я был более аккуратным способом.
12 ответов:
вы можете использовать свойство
Type.IsPrimitive, но будьте осторожны, потому что есть некоторые типы, которые мы можем считать примитивами, но они не являются, напримерDecimalиString.редактировать 1:добавил пример кода
вот пример кода:
if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... ) { // Is Primitive, or Decimal, or String }Edit 2: как @SLaks комментарии, есть и другие типы, которые, возможно, вы хотите рассматривать как примитивы, тоже. Я думаю, что вам придется добавить это вариации один на один.
редактировать 3: IsPrimitive = (логическое, байт, тип sbyte, типа INT16, типа uint16, int32 и тип uint32, типа int64, uint64 в, тип IntPtr, UIntPtr, типа char, Double и один), Пыльник примитивного типа для проверки(t == typeof (DateTime))
Я просто нашел этот вопрос, ища аналогичное решение, и подумал, что вам может быть интересен следующий подход с использованием
System.TypeCodeиSystem.Convert.легко сериализовать любой тип, который сопоставляется с
System.TypeCodeкромеSystem.TypeCode.Object, так что вы могли бы сделать:object PropertyValue = ... if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object) { string StringValue = Convert.ToString(PropertyValue); ... }преимущество этого подхода заключается в том, что вам не нужно называть все другие приемлемые непримитивные типы. Вы также можете немного изменить приведенный выше код для обработки любого типа, который реализует В разделе iconvertible.
мы делаем это так в нашем ORM:
Type t; bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));Я знаю, что с помощью
IsValueTypeНе самый лучший вариант (вы можете иметь свои собственные очень сложные структуры), но он работает в 99% случаев (и включает в себя Nullables).
из ответа @Ronnie Overby и комментария @jonathanconway я написал этот метод, который работает для Nullable и исключает пользовательские структуры.
public static bool IsSimpleType(Type type) { return type.IsPrimitive || new Type[] { typeof(Enum), typeof(String), typeof(Decimal), typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan), typeof(Guid) }.Contains(type) || Convert.GetTypeCode(type) != TypeCode.Object || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && IsSimpleType(type.GetGenericArguments()[0])) ; }в следующем примере :
struct TestStruct { public string Prop1; public int Prop2; } class TestClass1 { public string Prop1; public int Prop2; } [Test] public void Test1() { Assert.IsTrue(IsSimpleType(typeof(Enum))); Assert.IsTrue(IsSimpleType(typeof(String))); Assert.IsTrue(IsSimpleType(typeof(Char))); Assert.IsTrue(IsSimpleType(typeof(Guid))); Assert.IsTrue(IsSimpleType(typeof(Boolean))); Assert.IsTrue(IsSimpleType(typeof(Byte))); Assert.IsTrue(IsSimpleType(typeof(Int16))); Assert.IsTrue(IsSimpleType(typeof(Int32))); Assert.IsTrue(IsSimpleType(typeof(Int64))); Assert.IsTrue(IsSimpleType(typeof(Single))); Assert.IsTrue(IsSimpleType(typeof(Double))); Assert.IsTrue(IsSimpleType(typeof(Decimal))); Assert.IsTrue(IsSimpleType(typeof(SByte))); Assert.IsTrue(IsSimpleType(typeof(UInt16))); Assert.IsTrue(IsSimpleType(typeof(UInt32))); Assert.IsTrue(IsSimpleType(typeof(UInt64))); Assert.IsTrue(IsSimpleType(typeof(DateTime))); Assert.IsTrue(IsSimpleType(typeof(DateTimeOffset))); Assert.IsTrue(IsSimpleType(typeof(TimeSpan))); Assert.IsFalse(IsSimpleType(typeof(TestStruct))); Assert.IsFalse(IsSimpleType(typeof(TestClass1))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Char>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Guid>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Boolean>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Byte>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Int16>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Int32>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Int64>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Single>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Double>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<Decimal>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<SByte>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<UInt16>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<UInt32>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<UInt64>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<DateTime>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<DateTimeOffset>))); Assert.IsTrue(IsSimpleType(typeof(Nullable<TimeSpan>))); Assert.IsFalse(IsSimpleType(typeof(Nullable<TestStruct>))); }
вот как я это сделал.
static class PrimitiveTypes { public static readonly Type[] List; static PrimitiveTypes() { var types = new[] { typeof (Enum), typeof (String), typeof (Char), typeof (Guid), typeof (Boolean), typeof (Byte), typeof (Int16), typeof (Int32), typeof (Int64), typeof (Single), typeof (Double), typeof (Decimal), typeof (SByte), typeof (UInt16), typeof (UInt32), typeof (UInt64), typeof (DateTime), typeof (DateTimeOffset), typeof (TimeSpan), }; var nullTypes = from t in types where t.IsValueType select typeof (Nullable<>).MakeGenericType(t); List = types.Concat(nullTypes).ToArray(); } public static bool Test(Type type) { if (List.Any(x => x.IsAssignableFrom(type))) return true; var nut = Nullable.GetUnderlyingType(type); return nut != null && nut.IsEnum; } }
также хорошая возможность:
private static bool IsPrimitiveType(Type type) { return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object); }
предполагая, что у вас есть сигнатура функции, как это:
void foo<T>()вы можете добавить общее ограничение, чтобы разрешить только типы значений:
void foo<T>() where T : structобратите внимание, что это позволяет использовать не только примитивные типы для T, но и любой тип значения.
Мне нужно, чтобы сериализовать типы, для целей экспорта в XML. Для этого я перебрал объект и выбрал поля, которые были примитивными, перечислениями, типами значений или сериализуемыми. Это был результат моего запроса:
Type contextType = context.GetType(); var props = (from property in contextType.GetProperties() let name = property.Name let type = property.PropertyType let value = property.GetValue(context, (BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Public), null, null, null) where (type.IsPrimitive || type.IsEnum || type.IsValueType || type.IsSerializable) select new { Name = name, Value = value});Я использовал LINQ для перебора типов, а затем получить их имя и значение для хранения в таблице символов. Ключ находится в предложении "где", которое я выбрал для размышления. Я выбрал примитивные, перечислимые, типы значений и сериализуемые типы. Это позволило для строк и объектов DateTime пройти, как я ожидал.
Ура!
вот что у меня есть в моей библиотеке. Комментарии приветствуются.
сначала я проверяю IsValueType, так как он обрабатывает большинство типов, а затем String, поскольку он является вторым наиболее распространенным. Я не могу думать о примитиве, который не является типом значения, поэтому я не знаю, попадает ли эта нога в if.
Public Shared Function IsPersistable(Type As System.Type) As Boolean With TypeInformation.UnderlyingType(Type) Return .IsValueType OrElse Type = GetType(String) OrElse .IsPrimitive End With End Function Public Shared Function IsNullable(ByVal Type As System.Type) As Boolean Return (Type.IsGenericType) AndAlso (Type.GetGenericTypeDefinition() Is GetType(Nullable(Of ))) End Function Public Shared Function UnderlyingType(ByVal Type As System.Type) As System.Type If IsNullable(Type) Then Return Nullable.GetUnderlyingType(Type) Else Return Type End If End Functionтогда я могу использовать его так:
Public Shared Function PersistableProperties(Item As System.Type) As IEnumerable(Of System.Reflection.PropertyInfo) Return From PropertyInfo In Item.GetProperties() Where PropertyInfo.CanWrite AndAlso (IsPersistable(PropertyInfo.PropertyType)) Select PropertyInfo End Function
Я просто хочу поделиться мое решение. Возможно, это кому-то полезно.
public static bool IsPrimitiveType(Type fieldType) { return fieldType.IsPrimitive || fieldType.Namespace.Equals("System"); }
public static bool IsPrimitiveType(object myObject) { var myType = myObject.GetType(); return myType.IsPrimitive || myType.Namespace == null || myType.Namespace.Equals("System"); }Не забудьте проверить пустое пространство имен, потому что анонимные объекты не имеют назначенного пространства имен
вот еще один жизнеспособный вариант.
public static bool CanDirectlyCompare(Type type) { return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType; }
Comments