2011-09-30 9 views
14

Voglio convertire un oggetto in un tipo che verrà assegnato in fase di esecuzione.Convertire un tipo al volo in C# .NET

Ad esempio, si supponga di avere una funzione che assegna un valore di stringa (da TextBox or Dropdownlist) a Object.Property.

Come convertire il valore nel tipo corretto? Ad esempio, potrebbe essere un numero intero, una stringa o enum.

Public void Foo(object obj,string propertyName,object value) 
{ 
    //Getting type of the property og object. 
    Type t= obj.GetType().GetProperty(propName).PropertyType; 

    //Now Setting the property to the value . 
    //But it raise an error,because sometimes type is int and value is "2" 
    //or type is enum (e.a: Gender.Male) and value is "Male" 
    //Suppose that always the cast is valid("2" can be converted to int 2) 

    obj.GetType().GetProperty(propName).SetValue(obj, value, null); 
} 
+0

puoi dare un esempio dove questo sarebbe usato? Se non conosci il tipo concreto, perché dovresti lanciarlo? Hai pensato di andare dinamici? – Carsten

+0

Sai qual è il tipo quando passi l'argomento nel metodo 'Foo'? –

+0

@JamesJohnson Penso che puoi sempre scoprire se hai bisogno :-) – username

risposta

28

è necessario utilizzare la funzione Convert.ChangeType (...) (l'ingresso potrebbe essere solo con la stessa facilità di un oggetto ... Ho appena avuto una versione stringa di pre-cotti):

/// <summary> 
/// Sets a value in an object, used to hide all the logic that goes into 
///  handling this sort of thing, so that is works elegantly in a single line. 
/// </summary> 
/// <param name="target"></param> 
/// <param name="propertyName"></param> 
/// <param name="propertyValue"></param> 
public static void SetPropertyValueFromString(this object target,    
           string propertyName, string propertyValue) 
{ 
    PropertyInfo oProp = target.GetType().GetProperty(propertyName); 
    Type tProp = oProp.PropertyType; 

    //Nullable properties have to be treated differently, since we 
    // use their underlying property to set the value in the object 
    if (tProp.IsGenericType 
     && tProp.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
    { 
     //if it's null, just set the value from the reserved word null, and return 
     if (propertyValue == null) 
     { 
      oProp.SetValue(target, null, null); 
      return; 
     } 

     //Get the underlying type property instead of the nullable generic 
     tProp = new NullableConverter(oProp.PropertyType).UnderlyingType; 
    } 

    //use the converter to get the correct value 
    oProp.SetValue(target, Convert.ChangeType(propertyValue, tProp), null); 
} 
+0

L'unico svantaggio di questo approccio è che non funzionerà su tipi nullable. –

+0

Appena notato che hai qualche logica in là per i tipi nullable. –

+0

Convert.ChangeType() è soddisfacente anche se dovrei fare qualche controllo per l'enumerazione, tnx fordareh. – nAviD

2

Un convertitore di tipo universale è quello che cerchi!? Non è un'impresa facile ..

Prova questo approccio:

Universal Type Converter

È possibile in NuGet Install-Package UniversalTypeConverter

Inoltre, sta usando Generics fuori questione qui? Faciliterà la soluzione se si conosce almeno il tipo di target della conversione.

0

I 'non sono sicuro che funziona, ma fare un tentativo:

public static T To<T>(this IConvertible obj) 
{ 
    return (T)Convert.ChangeType(obj, typeof(T)); 
} 

Public void Foo(object obj,string propertyName,object value) 
{ 
    Type t= obj.GetType().GetProperty(propName).PropertyType; 
    obj.GetType().GetProperty(propName).SetValue(obj, value.To<t>(), null); 
} 
+0

Non funziona, perché il tipo generico t in A () deve essere definito in fase di compilazione. – nAviD

+0

@Navid: no, a causa del metodo di estensione che ho inserito all'inizio della mia risposta. Sono abbastanza sicuro che sarà valutato in fase di esecuzione ... – Marco

+0

Posso dire che questo non funziona e che @Navid è corretto. I metodi generici richiedono che il tipo sia fornito in fase di compilazione – workabyte

1

Ecco un altro modo si può fare, ma non sono sicuro

senza il supporto per i tipi generici:

public void Foo(object obj,string propertyName,object value) 
{ 
    //Getting type of the property og object. 
    Type type = obj.GetType().GetProperty(propertyName).PropertyType; 

    obj.GetType().GetProperty(propertyName).SetValue(obj, Activator.CreateInstance(type, value), null); 
} 

Con il supporto per i tipi generici:

public void Foo(object obj,string propertyName,object value) 
{ 
    //Getting type of the property og object. 
    Type type = obj.GetType().GetProperty(propertyName).PropertyType; 

    if (type.IsGenericType) 
     type = type.GetGenericArguments()[0]; 

    obj.GetType().GetProperty(propertyName).SetValue(obj, Activator.CreateInstance(type, value), null); 
} 
0

ho usato la funzione Converti in C#. Il modo in cui sto facendo la mia conversione è utilizzando la riflessione .:

Type type = this.myObject.GetType(); 

if (type.Name == "MyObjectClass") { 
var Voucherrequest = (MyObjectClass)Convert.ChangeType(myObject, typeof(MyObjectClass)); 

Questo è tutto a patto di saper che tipo che si desidera convertire in. Puoi persino fare un cambio e avere più tipi che vuoi riflettere.