web-dev-qa-db-ja.com

型がプリミティブかどうかをテストする方法

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

これは、intdoubleboolなどのプリミティブ型、およびプリミティブではないが、stringのように簡単にシリアル化できる他のタイプに対してのみこれを実行したい場合を除き、うまく機能します。リストや他のカスタムタイプなど、他のすべてを無視するようにします。

誰も私がこれを行う方法を提案できますか?または、どこかで許可するタイプを指定し、プロパティのタイプをオンにして、許可されているかどうかを確認する必要がありますか?それは少し厄介ですので、もっときれいな方法があればいいでしょう。

150
DaveDev

プロパティType.IsPrimitiveを使用できますが、プリミティブであると考えることができるタイプがいくつかありますが、そうではないので注意してください。たとえば、DecimalStringです。

編集1:サンプルコードを追加

サンプルコードを次に示します。

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

編集2:@ SLaks コメントと同様に、プリミティブとして扱いたい他のタイプもあります。このバリエーションを1つずつ追加する必要があると思います

編集3:IsPrimitive =(ブール、バイト、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Char、Double、およびシングル)、チェックするAnプリミティブ型のタイプ(t == typeof(DateTime))

169
Javier

同様の解決策を探しているときにこの質問を見つけたので、System.TypeCodeSystem.Convertを使用した次のアプローチに興味があるかもしれないと思いました。

System.TypeCode以外のSystem.TypeCode.Objectにマップされている型は簡単にシリアル化できるため、次のことができます。

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

このアプローチの利点は、他のすべての受け入れ可能な非プリミティブ型に名前を付ける必要がないことです。上記のコードを少し変更して、IConvertibleを実装する任意の型を処理することもできます。

51
Michael Petito

ORMで次のようにします。

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

IsValueTypeを使用することは最良のオプションではないことを知っています(独自の非常に複雑な構造体を持つことができます)が、99%のケースで機能します(Nullablesを含む)。

46
Alex

@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<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>)));
}
28
Xav987

ここに私がそれをした方法があります。

   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;
       }
   }
15
Ronnie Overby

また、良い可能性:

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

次のような関数シグネチャがあると仮定します。

void foo<T>() 

ジェネリック制約を追加して、値のタイプのみを許可できます。

void foo<T>() where T : struct

これにより、Tのプリミティブ型だけでなく、任意の値型が許可されることに注意してください。

3
eWolf

型を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を使用して型を反復処理し、名前と値を取得してシンボルテーブルに格納しました。キーは、反射のために選択した「where」節にあります。プリミティブな列挙型の値型とシリアル化可能な型を選択しました。これにより、文字列とDateTimeオブジェクトが期待どおりに処理されます。

乾杯!

2
JFalcon

ソリューションを共有したいだけです。おそらく誰にでも役立つでしょう。

public static bool IsPrimitiveType(Type fieldType)
{
   return fieldType.IsPrimitive || fieldType.Namespace.Equals("System");
}
1
Bahamut

これが私のライブラリにあるものです。コメントを歓迎します。

IsValueTypeはほとんどの型を処理するため最初にチェックし、次に2番目に一般的な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
1
toddmo

別の実行可能なオプションを次に示します。

public static bool CanDirectlyCompare(Type type)
{
    return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType;
}
0
user2023116
public static bool IsPrimitiveType(object myObject)
{
   var myType = myObject.GetType();
   return myType.IsPrimitive || myType.Namespace == null ||  myType.Namespace.Equals("System");
}

匿名オブジェクトには名前空間が割り当てられていないため、NULL名前空間を確認することを忘れないでください

0
iDusko