如何测试类型是否为原始

Dav*_*Dev 154 c# reflection primitive-types

我有一个代码块,将类型序列化为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);
}
Run Code Online (Sandbox Code Playgroud)

这个伟大的工程,但我希望它只是对基本类型,像这样做int,double,bool等,以及其他类型的不是原始的,但可以很容易地连载一样string.我希望它忽略列表和其他自定义类型之类的所有内容.

任何人都可以建议我这样做吗?或者我是否需要指定我想要允许的类型并打开属性的类型以查看是否允许它?这有点乱,所以如果我有一个更整洁的方式会很好.

Jav*_*ier 172

您可以使用该属性Type.IsPrimitive,但要小心,因为有些类型我们可以认为是基元,但它们不是,例如DecimalString.

编辑1: 添加了示例代码

这是一个示例代码:

if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... )
{
    // Is Primitive, or Decimal, or String
}
Run Code Online (Sandbox Code Playgroud)

编辑2:作为@SLaks注释,还有其他类型也许你想要作为基元处理.我认为你必须逐一添加这些变化.

编辑3: IsPrimitive =(布尔,字节,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,IntPtr,UIntPtr,Char,Double和Single),要检查的Anther Primitive-Like类型(t == typeof(DateTime) ))

  • 这是我编写的一种扩展方法,用于方便地运行@Javier和Michael Petito在答案中描述的测试:https://gist.github.com/3330614. (37认同)
  • 也许是`DateTime`,`TimeSpan`和`DateTimeOffset`. (10认同)
  • 您可以使用属性[Type.IsValueType](http://msdn.microsoft.com/en-us/library/system.type.isvaluetype.aspx)并仅添加字符串检查. (5认同)
  • 你需要使用逻辑或(`||`),而不是按位或(`|`). (2认同)

Mic*_*ito 53

我在寻找类似的解决方案时发现了这个问题,并且认为您可能对使用System.TypeCode和的以下方法感兴趣System.Convert.

很容易序列化映射到System.TypeCode其他类型的任何类型System.TypeCode.Object,因此您可以这样做:

object PropertyValue = ...
if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object)
{
    string StringValue = Convert.ToString(PropertyValue);
    ...
}
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是您不必为每个其他可接受的非基本类型命名.您还可以稍微修改上面的代码以处理任何实现IConvertible的类型.

  • 这很棒,我不得不为我自己的目的手动添加`Guid`(在我的定义中作为原语). (2认同)

Ale*_*lex 48

我们在ORM中这样做:

Type t;
bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));
Run Code Online (Sandbox Code Playgroud)

我知道使用IsValueType不是最好的选择(你可以拥有自己非常复杂的结构)但它适用于99%的情况(包括Nullables).

  • 如果使用IsValueType,为什么需要IsPrimitive?并非所有原始值都是值类型? (5认同)
  • @JoelFan十进制类型的IsPrimitive为false,但IsValueType为true (5认同)
  • @Lii你是对的,每个基本类型都将`IsValueType`设置为true,因此不需要检查`IsPrimitive`.干杯! (4认同)
  • @xhafan:您回答错误的问题。在这方面,所有结构都类似于“十进制”。但是,是否有类型的IsPrimitive返回true,而IsValueType返回false?如果没有这样的类型,那么就不需要`t.IsPrimitive`测试。 (2认同)

Xav*_*987 30

从@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]))
        ;
}
Run Code Online (Sandbox Code Playgroud)

使用以下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>)));
}
Run Code Online (Sandbox Code Playgroud)


Ron*_*rby 16

这就是我做到的.

   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;
       }
   }
Run Code Online (Sandbox Code Playgroud)


k3f*_*flo 6

也很有可能:

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

  • `String`和`Decimal`都不是原语. (3认同)