2009-06-05 9 views
7

Ich möchte eine universelle Laufzeittyp-Konvertierungsfunktion implementieren, die .Net TypeConverter verwendet, um die Konvertierung durchzuführen.Wie man einen .NET TypeConverter für einen bestimmten Typ sucht und aufruft?

Kann jemand einen TypConverter für einen bestimmten Typ nachschlagen und aufrufen?

Betrachten Sie diese C# Beispiel:

// 
// 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

Don verwende 'dotnet' nicht für ein Tag. –

Antwort

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); 
    } 

Sie auch bei Convert.ChangeType(obj, destinationType)

+2

Ich glaube nicht, Convert.ChangeType verwendet Typkonverter. – Patrik

+0

Schauen Sie auch auf Enum.ToObject, wenn Sie einen ganzzahligen Typ in einen tatsächlichen Aufzählungstyp konvertieren müssen. –

1

Neben Marc Antwort aussehen könnte, könnte man bedenkt, dass ASP.NET die Viewstate hat eine ähnliche Funktion zu dem, was Sie Ich möchte etwas tun. Es versucht die effizienteste Konvertierung zu finden.

Es könnte auch einen Blick auf this page und möglicherweise this one zu.

9

Hier ist der Code in einer unserer bestehenden Anwendungen ... nicht sicher, ob es ideal ist, aber es funktioniert gut für uns.

/// <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; 
    } 
} 

einfach die CustomTypeConversion Methode aufrufen, und gehen Sie weg ... wahrscheinlich ein wenig mehr, als Sie brauchen, aber gründliche zu sein, ist kein Verbrechen (oder ist es?).

+3

Beachten Sie, dass TypeConverter-Implementierungen zur Laufzeit hinzugefügt werden können (über TypeDescriptor) - und das Standardframework wird dies übernehmen - aber Reflektion (oben) * wird solche Zusätze nicht aufnehmen; System.ComponentModel wurde entwickelt, um zur Laufzeit sehr flexibel zu sein ... –

+0

Ah, gute Eins ... dieses Problem ist für uns (noch) aufgekommen - diesen Code gibt es schon seit einiger Zeit in unserer App; Es ist gut, ein neues Augenpaar zu haben. Vielen Dank! –

+0

Um ehrlich zu sein, würden Sie in den meisten Fällen den Unterschied nicht sehen ... es ist nicht üblich, dass Leute Laufzeitkonverter/Deskriptoren hinzufügen. Aber es ist möglich (ich habe ein Beispiel auf Stackoverflow irgendwo ...) –

1

Ich weiß nicht, wie robust es ist, aber ich manchmal diesen Code für generische Typumwandlung verwenden:

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

Ich weiß nicht, ob die Methode Change Verwendung Typeconverter ...

Verwandte Themen