Как проверить, является ли тип примитивным

У меня есть блок кода, который сериализует тип в тег Html.

Type t = typeof(T); // I pass  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 т. Д. И другие типы, которые не являются примитивными, но могут быть легко сериализованы как string . Я хочу, чтобы он игнорировал все остальное, как Списки и другие пользовательские типы.

Может ли кто-нибудь предложить, как я это делаю? Или мне нужно указать типы, которые я хочу разрешить, и включить тип свойства, чтобы узнать, разрешено ли это? Это немного грязно, так что было бы неплохо, если бы я был более аккуратным.

    Вы можете использовать свойство Type.IsPrimitive , но будьте осторожны, потому что есть некоторые типы, которые мы можем считать примитивами, но они не являются, например, Decimal и String .

    Редактировать 1: Добавлен образец кода

    Вот пример кода:

     if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... ) { // Is Primitive, or Decimal, or String } 

    Изменить 2: Как комментарии @SLaks , есть и другие типы, которые, возможно, вы хотите рассматривать как примитивы. Я думаю, что вам придется добавлять эти варианты один за другим .

    Edit 3: IsPrimitive = (Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double и Single), тип Anther Primitive-Like для проверки (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])) ; } 

    С помощью следующей TestCase:

     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))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsTrue(IsSimpleType(typeof(Nullable))); Assert.IsFalse(IsSimpleType(typeof(Nullable))); } 

    Вот как я это сделал.

      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() 

    Вы можете добавить общее ограничение, чтобы разрешить типы значений:

     void foo() 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, так как он является вторым наиболее распространенным. Я не могу придумать примитив, который не является типом значения, поэтому я не знаю, попадает ли эта нога когда-либо.

      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"); } 

    Не забудьте проверить пространство имен NULL, поскольку анонимным объектам не присвоено пространство имен

    Вот еще один жизнеспособный вариант.

     public static bool CanDirectlyCompare(Type type) { return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType; } 
    Давайте будем гением компьютера.