2013-07-23 22 views
10

ich eine Erweiterungsmethode, die ok arbeitet String-Werte in verschiedene Arten zu werfen, die etwa wie folgt aussieht:Allgemeine Methode Rückgabetyp als Typ-Parameter

public static T ToType<T> (this string value, T property) 
    { 
     object parsedValue = default(T); 
     Type type = property.GetType(); 

     try 
     { 
      parsedValue = Convert.ChangeType(value, type); 
     } 
     catch (ArgumentException e) 
     { 
      parsedValue = null; 
     } 

     return (T)parsedValue; 
    } 

Ich bin unglücklich über die Art und Weise dies aussieht, wenn Die Methode wird jedoch aufgerufen:

Angabe der Eigenschaft, nur um den Typ der Eigenschaft zu erhalten scheint redundant. Ich würde lieber eine Signatur wie diese verwenden:

public static T ToType<T> (this string value, Type type) { ... } 

und haben T enden, um den Typ des Typs zu sein. Dies würde Anrufe viel sauberer:

myObject.someProperty = stringData.ToType(typeof(decimal)); 

Wenn ich versuche, auf diese Weise zu nennen, jedoch beklagt der Herausgeber, dass der Rückgabetyp der Erweiterung Methode kann nicht von der Nutzung infered werden. Kann ich T mit dem Type-Argument verknüpfen?

Was fehlt mir?

Danke

+0

* Kann ich einen Link T auf dem Typ Argument * - Nicht directly¹. Sie vermischen Kompilierzeit und Laufzeit. Der C# -Compiler muss entscheiden, was "T" ist, wenn er einen Aufruf von "ToType" verarbeitet, während er Ihren Code kompiliert. OTOH 'type 'nimmt bei jedem Aufruf von' ToType' einen anderen Wert an. ------------------------------------------------- -------- ¹ - Sie * können * eine der Aromen der dynamischen Kompilation verwenden, aber es ist eine fortgeschrittene Technik und am besten für die wenigen Fälle reserviert, wenn es wirklich notwendig ist. –

+0

Vielen Dank für die Antworten und die Eingabe. – ZuluAlphaCharlie

Antwort

15

Ist das wonach Sie suchen? Ich habe einen zusätzlichen Fang für Fälle hinzugefügt, wo die Besetzung auch nicht gültig

Decimal i = stringName.ToType<Decimal>(); 

public static T ToType<T>(this string value) 
{ 
    object parsedValue = default(T); 
    try 
    { 
     parsedValue = Convert.ChangeType(value, typeof(T)); 
    } 
    catch (InvalidCastException) 
    { 
     parsedValue = null; 
    } 
    catch (ArgumentException) 
    { 
     parsedValue = null; 
    } 
    return (T)parsedValue; 
} 

bearbeiten

eine Verknüpfung Ansatz Anton Kommentar

if (typeof(T).IsValueType) 
    return default(T); 
+0

Das funktioniert. Vielen Dank! – ZuluAlphaCharlie

+0

"Spezifisches Spezifizieren des Typarguments" ist genau das, was er in der ersten Zeile seines Codes macht. Es ist eine spezielle Methodenaufrufssyntax mit den spitzen Klammern, obwohl es für Ihren Fall funktionieren sollte. – Katana314

+1

Sorry, Sayse. Es klappt.Ich habe die aus dem Aufruf – ZuluAlphaCharlie

2

Warum Eigenschaft überhaupt zu beheben ? Ändern Sie einfach, wie Sie Ihre Typvariable auf den Typ Ihres generischen Typs einstellen.

public static T ToType<T>(this string value) 
    { 
     object parsedValue = default(T); 
     Type type = typeof(T); 

     try 
     { 
      parsedValue = Convert.ChangeType(value, type); 
     } 
     catch (ArgumentException e) 
     { 
      parsedValue = null; 
     } 

     return (T) parsedValue; 
    } 

Verbrauch:

myObject.someProperty = stringData.ToType<decimal>() 
+0

Aha! Ich habe vergessen T im Anruf anzugeben ... ToType ()! Das funktioniert. Vielen Dank! – ZuluAlphaCharlie

0

Ich verwende dies für eine generische Umwandlung:

public bool ConvertTo<T>(object from, out T to) { 
     to = default(T); 
     if (from is T) { to = (T)from; return true; }           
     Type t = typeof(T); 
     //TypeConverter converter = p.converter == null ? TypeDescriptor.GetConverter(t) : p.converter; 
     TypeConverter converter = TypeDescriptor.GetConverter(t); 
     if ((converter != null) && (converter.CanConvertTo(t))) { 
      try { to = (T)converter.ConvertTo(null, culture, from, t); return true; } 
      catch { } 
     } 
     try { to = (T)Convert.ChangeType(from, t, culture); return true; } 
     catch { } 
     return false;                      
    } 

    public bool ConvertTo(object from, out object to, Type type) { 
     to = null; 
     if (from.GetType() == type) { to = from; return true; }  
     TypeConverter converter = TypeDescriptor.GetConverter(type); 
     if ((converter != null) && (converter.CanConvertTo(type))) { 
      try { to = converter.ConvertTo(null, culture, from, type); return true; } 
      catch { } 
     } 
     try { to = Convert.ChangeType(from, type, culture); return true; } 
     catch { } 
     return false;           
    } 

Vor Convert.ChangeType Aufruf, diese überprüft, ob es eine TypeConverter für die gegebene Variable.

Rufen Sie es auf diese Weise:

int i = 123; 
string s; 
if (ConvertTo<string>(i, out s) { 
    // use s 
} 
Verwandte Themen