2009-06-05 11 views
7

汎用のランタイム型変換関数を実装して、.Net TypeConvertersを使用して変換を行いたいと考えています。特定のタイプの.Net TypeConverterをルックアップして呼び出す方法は?

誰かが特定のタイプのTypeConverterをルックアップして呼び出す方法を知っていますか?

このC#の例を考えてみましょう:

// 
// Convert obj to the type specified by 'toType'. 
// 
object ConvertTo(object obj, Type toType) 
{ 
    if (TypeIsEqualOrDerivesFrom(obj.GetType(), toType)) <-- I know how to implement this. 
    { 
     // The type of obj is the same as the type specified by 'toType' or 
     // the type of obj derives from the type specified by 'toType'. 
     return obj; 
    } 

    if (TypeConverterExists(obj.GetType(), toType) <-- How do I implement this? 
    { 
     // There exists a type convertor that is capable of converting from 
     // the type of obj to the type specified by 'toType'. 
     return InvokeTypeConverter(obj, toType); <-- How do I implement this? 
    } 

    throw new TypeConversionFailedException(); 
} 
+0

ドンタグに 'dotnet'を使用しないでください。 –

答えて

31
TypeConverter converter = TypeDescriptor.GetConverter(sourceType); 
    if(converter.CanConvertTo(destinationType)) { 
     return converter.ConvertTo(obj, destinationType); 
    } 
    converter = TypeDescriptor.GetConverter(destinationType); 
    if(converter.CanConvertFrom(sourceType)) { 
     return converter.ConvertFrom(obj); 
    } 

あなたはまた、マルクの答えに加えてConvert.ChangeType(obj, destinationType)

+2

Convert.ChangeTypeは型変換器を使用しているとは思わない。 – Patrik

+0

また、整数型を実際の列挙型に変換する必要がある場合は、Enum.ToObjectを参照してください。 –

1

で見ることができる、あなたはASP.NETのViewStateが何に似た機能を行うことを検討するかもしれないがやりたい最も効率的な変換を見つけようとします。

this pageとおそらくthis oneをご覧ください。

9

これは既存のアプリケーションの1つで使用されているコードです...理想的かどうかはわかりませんが、うまく機能します。

/// <summary> 
/// Attempts to convert a value using any customer TypeConverters applied to the member 
/// </summary> 
/// <param name="value">Object containing the value to be assigned</param> 
/// <param name="member">Member to be assigned to</param> 
/// <returns><paramref name="value"/> converted to the appropriate type</returns> 
public static Object CustomTypeConversion (object value, MemberInfo member) 
{ 
    if (value == null || value == DBNull.Value) 
     return value; 

    if (member == null) 
     throw new ArgumentNullException (); 

    List<TypeConverter> converters = GetCustomTypeConverters (member); 

    foreach (TypeConverter c in converters) 
    { 
     if (c.CanConvertFrom (value.GetType ())) 
      return c.ConvertFrom (value); 
    } 

    if (member is PropertyInfo) 
    { 
     PropertyInfo prop = member as PropertyInfo; 
     return ConvertToNative(value , prop.PropertyType); 
    } 
    return ConvertToNative (value, member.MemberType.GetType ()); 
} 

/// <summary> 
/// Extracts and instantiates any customer type converters assigned to a 
/// derivitive of the <see cref="System.Reflection.MemberInfo"/> property 
/// </summary> 
/// <param name="member">Any class deriving from MemberInfo</param> 
/// <returns>A list of customer type converters, empty if none found</returns> 
public static List<TypeConverter> GetCustomTypeConverters (System.Reflection.MemberInfo member) 
{ 
    List<TypeConverter> result = new List<TypeConverter>(); 

    try 
    { 
     foreach (TypeConverterAttribute a in member.GetCustomAttributes(typeof(TypeConverterAttribute) , true)) 
     { 
      TypeConverter converter = Activator.CreateInstance(Type.GetType(a.ConverterTypeName)) as TypeConverter; 

      if (converter != null) 
       result.Add(converter); 
     } 
    } 
    catch 
    { 
     // Let it go, there were no custom converters 
    } 

    return result; 
} 

/// <summary> 
/// Attempts to cast the incoming database field to the property type 
/// </summary> 
/// <param name="value">Database value to cast</param> 
/// <param name="castTo">Type to cast to</param> 
/// <returns>The converted value, if conversion failed the original value will be returned</returns> 
public static object ConvertToNative (object value , Type castTo) 
{ 
    try 
    { 
     return Convert.ChangeType(value , castTo , System.Threading.Thread.CurrentThread.CurrentCulture); 
    } 
    catch 
    { 
     return value; 
    } 
} 

だけCustomTypeConversionメソッドを呼び出すと離れてあなたが行く...あなたが必要とするよりも、おそらくもう少しなく、徹底していることは犯罪ではありません(またはそれがあります?)。

+3

TypeConverterの実装は実行時に(TypeDescriptor経由で)追加することができます。標準フレームワークはそれを選択しますが、リフレクション(上記)*はそのような追加を取りません。 System.ComponentModelは実行時に非常に柔軟に設計されています... –

+0

ああ、良い1つ...その問題は私たちのために現れています(まだ) - このコードはしばらくの間、私たちのアプリの周りにあります。新鮮な目をしてみるのは良いことです。ありがとう! –

+0

正直言って、ほとんどの場合、違いは見られません。人々がランタイムコンバータ/ディスクリプタを追加するのは一般的ではありません。しかし、可能です(私はどこかにstackoverflowの例を持っている...) –

1

私はそれがどのように堅牢知りませんが、私は時々ジェネリック型変換のために、このコードを使用します。

public T ConvertTo<T>(object value) 
{ 
    return (T)Convert.ChangeType(value, typeof(T)); 
} 

変更タイプの方法の使用TypeConverters場合、私は知らない...

関連する問題