How To Test if Type is Primitive
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(string),
typeof(decimal),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(TimeSpan),
typeof(Guid)
}.Contains(type) ||
type.IsEnum ||
Convert.GetTypeCode(type) != TypeCode.Object ||
(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && IsSimpleType(type.GetGenericArguments()[0]))
;
}
With the following TestCase :
struct TestStruct
{
public string Prop1;
public int Prop2;
}
class TestClass1
{
public string Prop1;
public int Prop2;
}
enum TestEnum { TheValue }
[Test]
public void Test1()
{
Assert.IsTrue(IsSimpleType(typeof(TestEnum)));
Assert.IsTrue(IsSimpleType(typeof(string)));
Assert.IsTrue(IsSimpleType(typeof(char)));
Assert.IsTrue(IsSimpleType(typeof(Guid)));
Assert.IsTrue(IsSimpleType(typeof(bool)));
Assert.IsTrue(IsSimpleType(typeof(byte)));
Assert.IsTrue(IsSimpleType(typeof(short)));
Assert.IsTrue(IsSimpleType(typeof(int)));
Assert.IsTrue(IsSimpleType(typeof(long)));
Assert.IsTrue(IsSimpleType(typeof(float)));
Assert.IsTrue(IsSimpleType(typeof(double)));
Assert.IsTrue(IsSimpleType(typeof(decimal)));
Assert.IsTrue(IsSimpleType(typeof(sbyte)));
Assert.IsTrue(IsSimpleType(typeof(ushort)));
Assert.IsTrue(IsSimpleType(typeof(uint)));
Assert.IsTrue(IsSimpleType(typeof(ulong)));
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(TestEnum?)));
Assert.IsTrue(IsSimpleType(typeof(char?)));
Assert.IsTrue(IsSimpleType(typeof(Guid?)));
Assert.IsTrue(IsSimpleType(typeof(bool?)));
Assert.IsTrue(IsSimpleType(typeof(byte?)));
Assert.IsTrue(IsSimpleType(typeof(short?)));
Assert.IsTrue(IsSimpleType(typeof(int?)));
Assert.IsTrue(IsSimpleType(typeof(long?)));
Assert.IsTrue(IsSimpleType(typeof(float?)));
Assert.IsTrue(IsSimpleType(typeof(double?)));
Assert.IsTrue(IsSimpleType(typeof(decimal?)));
Assert.IsTrue(IsSimpleType(typeof(sbyte?)));
Assert.IsTrue(IsSimpleType(typeof(ushort?)));
Assert.IsTrue(IsSimpleType(typeof(uint?)));
Assert.IsTrue(IsSimpleType(typeof(ulong?)));
Assert.IsTrue(IsSimpleType(typeof(DateTime?)));
Assert.IsTrue(IsSimpleType(typeof(DateTimeOffset?)));
Assert.IsTrue(IsSimpleType(typeof(TimeSpan?)));
Assert.IsFalse(IsSimpleType(typeof(TestStruct?)));
}
I just found this question while looking for a similar solution, and thought you might be interested in the following approach using System.TypeCode
and System.Convert
.
It is easy to serialize any type that is mapped to a System.TypeCode
other than System.TypeCode.Object
, so you could do:
object PropertyValue = ...
if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object)
{
string StringValue = Convert.ToString(PropertyValue);
...
}
The advantage with this approach is you don't have to name every other acceptable non-primitive type. You could also modify the above code slightly to handle any type that implements IConvertible.
You can use the property Type.IsPrimitive
, but be carefull because there are some types that we can think that are primitives, but they aren´t, for example Decimal
and String
.
Edit 1: Added sample code
Here is a sample code:
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 you want to treat as primitives, too. I think that you´ll have to add this variations one by one.
Edit 3: IsPrimitive = (Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single), Anther Primitive-Like type to check (t == typeof(DateTime))
We do it like this in our ORM:
Type t;
bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));
I know that using IsValueType
is not the best option (you can have your own very complex structs) but it works in 99% cases (and includes Nullables).