Cómo probar si el tipo es primitivo

Tengo un bloque de código que serializa un tipo en una etiqueta 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); } 

Esto funciona muy bien, excepto que quiero que solo haga esto para tipos primitivos, como int , double , bool , etc., y otros tipos que no son primitivos, pero que se pueden serializar fácilmente como string . Quiero que ignore todo lo demás, como listas y otros tipos personalizados.

¿Alguien puede sugerir cómo hago esto? ¿O debo especificar los tipos que quiero permitir en algún lugar y activar el tipo de propiedad para ver si está permitido? Eso es un poco desordenado, así que estaría bien si hubiera una manera más ordenada.

Puede usar la propiedad Type.IsPrimitive , pero tenga cuidado porque hay algunos tipos que podemos pensar que son primitivos, pero no lo son, por ejemplo, Decimal y String .

Edición 1: código de muestra agregado

Aquí hay un código de muestra:

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

Editar 2: como comentarios de @SLaks , hay otros tipos que quizás desee tratar como primitivos, también. Creo que tendrás que agregar estas variaciones una a una .

Edición 3: IsPrimitive = (Booleano, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Doble y Único), tipo Anther Primitive-Like para verificar (t == typeof (DateTime) )

Acabo de encontrar esta pregunta mientras buscaba una solución similar, y pensé que podría estar interesado en el siguiente enfoque utilizando System.TypeCode y System.Convert .

Es fácil serializar cualquier tipo que esté mapeado en un System.TypeCode no sea System.TypeCode.Object , por lo que podría hacer:

 object PropertyValue = ... if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object) { string StringValue = Convert.ToString(PropertyValue); ... } 

La ventaja de este enfoque es que no tiene que nombrar cualquier otro tipo no primitivo aceptable. También puede modificar ligeramente el código anterior para manejar cualquier tipo que implemente IConvertible.

Lo hacemos así en nuestro ORM:

 Type t; bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string)); 

Sé que usar IsValueType no es la mejor opción (puedes tener tus propias estructuras muy complejas) pero funciona en un 99% de casos (e incluye Nullables).

Desde @Ronnie Overby response y @jonathanconway comment, escribí este método que funciona para Nullable y excluyo las estructuras de usuario.

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

Con el siguiente 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))); } 

Así es como lo hice.

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

También una buena posibilidad:

 private static bool IsPrimitiveType(Type type) { return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object); } 

Asumiendo que tienes una firma de función como esta:

 void foo() 

Puede agregar una restricción genérica para permitir solo los tipos de valor:

 void foo() where T : struct 

Tenga en cuenta que esto permite no solo tipos primitivos para T, sino también cualquier tipo de valor.

Tenía la necesidad de serializar tipos para exportarlos a XML. Para hacer esto, itere a través del objeto y opté por campos primitivos, enum, value types o serializables. Este fue el resultado de mi consulta:

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

Usé LINQ para repetir los tipos, luego obtuve su nombre y valor para almacenarlos en una tabla de símbolos. La clave está en la cláusula ‘dónde’ que elegí para la reflexión. Elegí primitivos, enumerados, tipos de valores y tipos serializables. Esto permitió que las cadenas y los objetos DateTime aparecieran como esperaba.

¡Aclamaciones!

Esto es lo que tengo en mi biblioteca. Los comentarios son bienvenidos

Primero compruebo IsValueType, ya que maneja la mayoría de los tipos, luego String, ya que es el segundo más común. No puedo pensar en un primitivo que no sea un tipo de valor, así que no sé si ese tramo del si alguna vez es golpeado.

  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 

Entonces puedo usarlo así:

  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 

Solo quiero compartir mi solución. Tal vez sea útil para cualquiera.

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

No olvides verificar el espacio de nombres NULL, porque los objetos anónimos no tienen espacio de nombres asignado

Aquí hay otra opción viable.

 public static bool CanDirectlyCompare(Type type) { return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType; }