我有一个代码块,可以将类型序列化为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);
}
这很好用,除了我希望它只对原始类型执行此操作,例如int
,double
,bool
等,以及其他非原始类型但可以是像string
一样容易序列化。我希望它忽略其他一切,如Lists&amp;其他自定义类型。
有人可以建议我这样做吗?或者我是否需要指定我想要允许的类型并打开属性的类型以查看是否允许它?这有点乱,所以如果我有一个更整洁的方式会很好。
答案 0 :(得分:166)
您可以使用属性Type.IsPrimitive
,但要小心,因为我们可以认为某些类型是基元,但它们不是,例如Decimal
和String
。
编辑1: 添加了示例代码
以下是示例代码:
if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... )
{
// Is Primitive, or Decimal, or String
}
编辑2:作为@SLaks条评论,您还可以将其他类型视为基元。我认为你必须逐个添加 的。。
编辑3: IsPrimitive =(布尔,字节,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,IntPtr,UIntPtr,Char,Double和Single), 要检查的Anther Primitive-Like类型(t == typeof(DateTime))
答案 1 :(得分:51)
我在寻找类似解决方案时发现了这个问题,并认为您可能对使用System.TypeCode
和System.Convert
的以下方法感兴趣。
很容易序列化映射到System.TypeCode
以外的System.TypeCode.Object
的任何类型,所以你可以这样做:
object PropertyValue = ...
if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object)
{
string StringValue = Convert.ToString(PropertyValue);
...
}
这种方法的优点是您不必为每个其他可接受的非基本类型命名。您还可以稍微修改上面的代码来处理任何实现IConvertible的类型。
答案 2 :(得分:42)
我们在ORM中这样做:
Type t;
bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));
我知道使用IsValueType
并不是最好的选择(你可以拥有自己非常复杂的结构)但它适用于99%的情况(包括Nullables)。
答案 3 :(得分:28)
从@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>)));
}
答案 4 :(得分:15)
我是这样做的。
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;
}
}
答案 5 :(得分:5)
也是一个很好的可能性:
private static bool IsPrimitiveType(Type type)
{
return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);
}
答案 6 :(得分:3)
假设你有这样的功能签名:
void foo<T>()
您可以添加通用约束以仅允许值类型:
void foo<T>() where T : struct
请注意,这不仅允许T的基本类型,还允许任何值类型。
答案 7 :(得分:2)
我需要序列化类型,以便将它们导出到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对象按照我的预期通过。
干杯!
答案 8 :(得分:1)
这就是我在我的图书馆里所拥有的。欢迎提出意见。
我首先检查IsValueType,因为它处理大多数类型,然后是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
答案 9 :(得分:1)
我只想分享我的解决方案。也许它对任何人都有用。
public static bool IsPrimitiveType(Type fieldType)
{
return fieldType.IsPrimitive || fieldType.Namespace.Equals("System");
}
答案 10 :(得分:0)
mat <- function(x) {
class(x) <- "mat"
x
}
`[.mat` <- function(x, i, j) {
y <- mat(unclass(x)[i, j])
invisible(y)
}
print.mat <- function(x, ...) {
invisible(x)
}
test <- mat(matrix(1:10, ncol = 2))
test[1, 1]
# Nothing is printed
不要忘记检查NULL命名空间,因为匿名对象没有指定的命名空间
答案 11 :(得分:0)
这是另一个可行的选择。
public static bool CanDirectlyCompare(Type type)
{
return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType;
}