Jak sprawdzić czy typ jest prymitywny

Mam blok kodu, który serializuje typ do znacznika 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);
}

To działa świetnie, tylko chcę, żeby to robił tylko dla prymitywnych typów, jak int, double, bool itd, i inne typy, które nie są prymitywne, ale można je łatwo serializować jak string. Chcę, aby zignorował Wszystko inne, takie jak listy i inne niestandardowe typy.

Czy ktoś może zasugerować, Jak to zrobić? Czy muszę określić typy, na które chcę gdzieś zezwolić i włączyć typ właściwości, aby sprawdzić, czy jest wolno? To trochę bałagan, więc byłoby miło, gdybym był bardziej uporządkowany.
Author: DaveDev, 2010-03-14

12 answers

Możesz użyć właściwości Type.IsPrimitive, ale bądź ostrożny, ponieważ istnieją pewne typy, które możemy uznać za prymitywne, ale nie są, na przykład Decimal i String.

Edytuj 1: Dodano przykładowy kod

Oto przykładowy kod:

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

Edit 2: as @SLaks comments, there are other types that maybe want to treat as primitives, too. Myślę, że będziesz musiał dodać te wariacje jeden po drugim.

Edytuj 3: IsPrimitive = (Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single), Anther-Like type to check (t = = typeof (DateTime))

 151
Author: Javier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:19

Właśnie znalazłem to pytanie szukając podobnego rozwiązania i pomyślałem, że może zainteresować Cię następujące podejście przy użyciu System.TypeCode i System.Convert.

Łatwo jest serializować dowolny typ, który jest odwzorowany na System.TypeCode inny niż System.TypeCode.Object, więc możesz to zrobić:

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

Zaletą tego podejścia jest to, że nie musisz wymieniać wszystkich innych akceptowalnych nie-prymitywnych typów. Możesz również nieznacznie zmodyfikować powyższy kod, aby obsługiwał każdy typ, który implementuje IConvertible.

 48
Author: Michael Petito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-18 23:31:53

Robimy to tak w naszym ORM:

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

Wiem, że użycie IsValueType nie jest najlepszą opcją (możesz mieć własne bardzo złożone struktury), ale działa w 99% przypadków (i zawiera Nullables).

 38
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-17 02:17:59

From @ Ronnie Overby response and @ jonathanconway comment, I wrote this method that works for Nullable, and exclude user structs.

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

Z następującym testem:

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>)));
}
 24
Author: Xav987,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-01 17:47:01

Oto Jak to zrobiłem.

   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;
       }
   }
 14
Author: Ronnie Overby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-06 20:50:06

Również dobra możliwość:

private static bool IsPrimitiveType(Type type)
{
    return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);
}
 5
Author: k3flo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 09:50:28

Zakładając, że masz taką sygnaturę funkcji:

void foo<T>() 

Możesz dodać ogólne Ograniczenie, aby zezwolić tylko na typy wartości:

void foo<T>() where T : struct

Zauważ, że pozwala to nie tylko na typy prymitywne dla T, ale na każdy typ wartości.

 3
Author: eWolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-14 15:04:27

Miałem potrzebę serializacji typów w celu eksportowania ich do XML. Aby to zrobić, iterowałem przez obiekt i wybrałem pola, które były prymitywne, enum, typy wartości lub serializowalne. To wynik mojego zapytania:

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

Użyłem LINQ do iteracji typów, a następnie uzyskać ich nazwę i wartość do przechowywania w tabeli symboli. Klucz znajduje się w klauzuli "gdzie", którą wybrałem do refleksji. Wybrałem prymitywne, wyliczane, typy wartości i typy serializowalne. To pozwoliło aby ciągi i Obiekty DateTime przeszły tak, jak oczekiwałem.

Zdrówko!
 2
Author: JFalcon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-18 14:55:23

To jest to, co mam w mojej bibliotece. Komentarze są mile widziane.

Sprawdzam najpierw IsValueType, ponieważ obsługuje większość typów, a następnie String, ponieważ jest drugim najczęściej używanym. Nie mogę myśleć o prymitywie, który nie jest typem wartości, więc nie wiem, czy ta noga if kiedykolwiek zostanie uderzona.

  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

Wtedy mogę go użyć w ten sposób:

  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
 1
Author: toddmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-22 16:38:33

Chcę się podzielić moim rozwiązaniem. Może komuś się przyda.

public static bool IsPrimitiveType(Type fieldType)
{
   return fieldType.IsPrimitive || fieldType.Namespace.Equals("System");
}
 1
Author: Bahamut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-27 08:07:25
public static bool IsPrimitiveType(object myObject)
{
   var myType = myObject.GetType();
   return myType.IsPrimitive || myType.Namespace == null ||  myType.Namespace.Equals("System");
}

Nie zapomnij sprawdzić NULL przestrzeni nazw, ponieważ obiekty anonimowe nie mają przypisanej przestrzeni nazw

 0
Author: iDusko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 21:20:58

Oto kolejna realna opcja.

public static bool CanDirectlyCompare(Type type)
{
    return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType;
}
 0
Author: user2023116,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 22:39:51