如何testingtypes是否是原始的
我有一段代码将一个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); }
这很好,除了我希望它只为原始types,如int
, double
, bool
等,以及其他types不是原始的,但可以像string
一样容易序列化。 我希望它忽略像列表和其他自定义types的一切。
任何人都可以build议我怎么做? 还是我需要指定我想要允许的types,并切换属性的types,看看是否允许? 这有点乱,所以如果我有一个更整洁的方式会很好。
您可以使用Type.IsPrimitive
属性,但要小心,因为有些types我们可以认为是基元,但它们不是,例如Decimal
和String
。
编辑1: 添加示例代码
这是一个示例代码:
if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... ) { // Is Primitive, or Decimal, or String }
编辑2:作为@SLaks的评论,还有其他types,也许你想作为原语对待。 我认为你必须逐个添加这个变体。
编辑3: IsPrimitive =(布尔,字节,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,IntPtr,UIntPtr,字符,双,单),花药Primitive-Liketypes来检查(t == typeof(DateTime ))
在寻找类似的解决scheme时,我刚刚发现了这个问题,并且认为你可能会对使用System.TypeCode
和System.Convert
的以下方法感兴趣。
很容易序列化映射到System.TypeCode
以外的System.TypeCode.Object
任何types,所以你可以这样做:
object PropertyValue = ... if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object) { string StringValue = Convert.ToString(PropertyValue); ... }
这种方法的优点是你不必命名其他所有可接受的非原始types。 你也可以修改上面的代码来处理任何实现IConvertible的types。
我们在我们的ORM中这样做:
Type t; bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));
我知道,使用IsValueType
不是最好的select(你可以有自己非常复杂的结构),但它在99%的情况下工作
从@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>))); }
这是我做的。
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; } }
另外一个很好的可能性
private static bool IsPrimitiveType(Type type) { return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object); }
假设你有这样的函数签名:
void foo<T>()
您可以添加一个通用约束来仅允许值types:
void foo<T>() where T : struct
注意,这不仅允许T的基本types,而且还允许任何值types。
为了将它们导出到XML,我需要序列化types。 为了做到这一点,我迭代了对象,并select了原始,枚举,值types或可序列化的字段。 这是我查询的结果:
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遍历types,然后获取它们的名称和值存储在符号表中。 关键在于我select反思的“where”条款。 我select了原始的,枚举的,值types和可序列化的types。 这允许string和DateTime对象按照我的预期通过。
干杯!
我只想分享我的解决scheme。 也许这对任何人都有用。
public static bool IsPrimitiveType(Type fieldType) { return fieldType.IsPrimitive || fieldType.Namespace.Equals("System"); }
这是我在图书馆里所拥有的。 欢迎评论。
我首先检查IsValueType,因为它处理大多数types,然后是String,因为它是第二常见的types。 我无法想象一个不是价值型的原始物体,所以我不知道这个物体是否会被击中。
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
public static bool IsPrimitiveType(object myObject) { var myType = myObject.GetType(); return myType.IsPrimitive || myType.Namespace == null || myType.Namespace.Equals("System"); }
不要忘记检查NULL命名空间,因为匿名对象没有分配的命名空间
这是另一个可行的select。
public static bool CanDirectlyCompare(Type type) { return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType; }