Come verificare se il tipo è primitivo

Ho un blocco di codice che serializza un tipo in un tag 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); } 

Funziona alla grande, tranne che voglio farlo solo per i tipi primitivi, come int , double , bool ecc, e altri tipi che non sono primitivi ma possono essere serializzati facilmente come una string . Voglio che ignori tutto il resto come elenchi e altri tipi personalizzati.

Qualcuno può suggerire come lo faccio? O devo specificare i tipi che voglio consentire da qualche parte e triggersre il tipo di proprietà per vedere se è permesso? È un po ‘complicato, quindi sarebbe bello se io avessi un modo più ordinato.

Puoi usare la proprietà Type.IsPrimitive , ma Type.IsPrimitive attenzione perché ci sono alcuni tipi che possiamo pensare che siano primitive, ma non lo sono, ad esempio Decimal e String .

Modifica 1: aggiunto codice di esempio

Ecco un codice di esempio:

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

Modifica 2: come commenti di @SLaks , ci sono altri tipi che forse vuoi trattare anche come primitivi. Penso che dovrai aggiungere queste variazioni una alla volta .

Modifica 3: IsPrimitive = (Booleano, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double e Single), tipo Anther Primitive-Like da verificare (t == typeof (DateTime ))

Ho appena trovato questa domanda mentre cercavo una soluzione simile e ho pensato che potreste essere interessati al seguente approccio usando System.TypeCode e System.Convert .

È facile serializzare qualsiasi tipo mappato su un System.TypeCode diverso da System.TypeCode.Object , quindi è ansible eseguire:

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

Il vantaggio di questo approccio è che non è necessario nominare ogni altro tipo non primitivo accettabile. È inoltre ansible modificare leggermente il codice precedente per gestire qualsiasi tipo che implementa IConvertible.

Lo facciamo così nel nostro ORM:

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

So che usare IsValueType non è l’opzione migliore (puoi avere le tue strutture molto complesse) ma funziona nel 99% dei casi (e include Nullables).

Dalla risposta @Ronnie Overby e dal commento @jonathanconway, ho scritto questo metodo che funziona per Nullable ed esclude le strutture utente.

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

Ecco come l’ho fatto.

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

Anche una buona possibilità:

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

Supponendo che tu abbia una firma di funzione come questa:

 void foo() 

È ansible aggiungere un vincolo generico per consentire solo tipi di valori:

 void foo() where T : struct 

Si noti che questo consente non solo i tipi primitivi per T, ma qualsiasi tipo di valore.

Ho avuto bisogno di serializzare i tipi allo scopo di esportarli in XML. Per fare ciò, ho iterato l’object e ho optato per i campi che erano primitivi, enum, tipi di valori o serializzabili. Questo è stato il risultato della mia domanda:

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

Ho usato LINQ per iterare attraverso i tipi, quindi ottenere il loro nome e valore da memorizzare in una tabella dei simboli. La chiave è nella clausola ‘where’ che ho scelto per la riflessione. Ho scelto tipi di valori primitivi, enumerati, e serializzabili. Ciò consentiva l’arrivo di stringhe e oggetti DateTime come previsto.

Saluti!

Questo è quello che ho nella mia biblioteca. I commenti sono i benvenuti

Prima controllo IsValueType, poiché gestisce la maggior parte dei tipi, quindi String, poiché è il secondo più comune. Non riesco a pensare a un primitivo che non sia un tipo di valore, quindi non so se quella gamba del mai se verrà colpita.

  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 

Quindi posso usarlo in questo modo:

  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 

Voglio solo condividere la mia soluzione. Forse è utile a chiunque.

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

Non dimenticare di controllare lo spazio dei nomi NULL, perché gli oggetti anonimi non hanno uno spazio dei nomi assegnato

Ecco un’altra opzione praticabile.

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