型を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
のように簡単にシリアル化できる他のタイプに対してのみこれを実行したい場合を除き、うまく機能します。リストや他のカスタムタイプなど、他のすべてを無視するようにします。
誰も私がこれを行う方法を提案できますか?または、どこかで許可するタイプを指定し、プロパティのタイプをオンにして、許可されているかどうかを確認する必要がありますか?それは少し厄介ですので、もっときれいな方法があればいいでしょう。
プロパティType.IsPrimitive
を使用できますが、プリミティブであると考えることができるタイプがいくつかありますが、そうではないので注意してください。たとえば、Decimal
とString
です。
編集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))
同様の解決策を探しているときにこの質問を見つけたので、System.TypeCode
とSystem.Convert
を使用した次のアプローチに興味があるかもしれないと思いました。
System.TypeCode
以外のSystem.TypeCode.Object
にマップされている型は簡単にシリアル化できるため、次のことができます。
object PropertyValue = ...
if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object)
{
string StringValue = Convert.ToString(PropertyValue);
...
}
このアプローチの利点は、他のすべての受け入れ可能な非プリミティブ型に名前を付ける必要がないことです。上記のコードを少し変更して、IConvertibleを実装する任意の型を処理することもできます。
ORMで次のようにします。
Type t;
bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));
IsValueType
を使用することは最良のオプションではないことを知っています(独自の非常に複雑な構造体を持つことができます)が、99%のケースで機能します(Nullablesを含む)。
@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>()
ジェネリック制約を追加して、値のタイプのみを許可できます。
void foo<T>() where T : struct
これにより、Tのプリミティブ型だけでなく、任意の値型が許可されることに注意してください。
型を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オブジェクトが期待どおりに処理されます。
乾杯!
ソリューションを共有したいだけです。おそらく誰にでも役立つでしょう。
public static bool IsPrimitiveType(Type fieldType)
{
return fieldType.IsPrimitive || fieldType.Namespace.Equals("System");
}
これが私のライブラリにあるものです。コメントを歓迎します。
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
別の実行可能なオプションを次に示します。
public static bool CanDirectlyCompare(Type type)
{
return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType;
}
public static bool IsPrimitiveType(object myObject)
{
var myType = myObject.GetType();
return myType.IsPrimitive || myType.Namespace == null || myType.Namespace.Equals("System");
}
匿名オブジェクトには名前空間が割り当てられていないため、NULL名前空間を確認することを忘れないでください