2009-09-28 4 views
10

Provo a impostare dinamicamente una proprietà Nullable <>.Imposta proprietà Nullable <> per riflessione

ricevo la mia proprietà ex:

PropertyInfo property = class.GetProperty("PropertyName"); // My property is Nullable<> at this time So the type could be a string or int 

voglio impostare la mia proprietà dalla riflessione come

property.SetValue(class,"1256",null); 

non funziona quando la mia proprietà è un Nullable <> generico. Quindi cerco di trovare un modo per impostare la mia proprietà.

di conoscere il tipo di mia nullable <> proprietà eseguo

Nullable.GetUnderlyingType(property.PropertyType) 

Qualche idea?

  • cerco di creare un'istanza della mia Nullable <> proprietà con

    var = nullVar Activator.CreateInstance (typeof (Nullable <>). MakeGenericType (nuovo tipo di [] {Nullable.GetUnderlyingType (proprietà .Tipo di proprietà) }));

Ma nullVar è sempre nullo

+0

funziona quando si imposta un intero invece di una stringa? '" 1256 "' è una stringa, non un intero. –

+0

Funzionerà, ma il punto è che non conosco il tipo di proprietà nullable. Potrei usare Nullable.GetUnderlyingType (property.PropertyType) per ottenere il tipo –

+0

'Nullable <>' non posso usare 'string' per il tipo sottostante poichè' string' è un tipo di riferimento. In altre parole 'typeof (Nullable <>). MakeGenericType (t);' andrà bene se 't == typeof (int)', ma esploderà (vincolo non incontrato) con 't == typeof (stringa)' . Quindi 'Nullable <>' non agirà in alcun modo come una sorta di "tipo comune" per tipi di riferimento e tipi di valori nullable. –

risposta

13

Se si desidera convertire una stringa arbitraria al tipo di fondo della Nullable, è possibile utilizzare la classe Convert:

var propertyInfo = typeof(Foo).GetProperty("Bar"); 
object convertedValue = null; 
try 
{ 
    convertedValue = System.Convert.ChangeType("1256", 
     Nullable.GetUnderlyingType(propertyInfo.PropertyType)); 
} 
catch (InvalidCastException) 
{ 
    // the input string could not be converted to the target type - abort 
    return; 
} 
propertyInfo.SetValue(fooInstance, convertedValue, null); 

Questo esempio funziona se il tipo di destinazione è di tipo int corta, lunga (o varianti senza segno, poiché la stringa di input rappresenta un numero non negativo), double, float o decimal. Avvertenza: questo non è un codice veloce.

+0

Lo proverò, in questo momento tink sei la risposta più vicina che cerco –

+0

Funziona grazie –

+0

Funziona grazie –

9

Se è un int nullable, avrete bisogno di utilizzare un parametro int, non una stringa.

property.SetValue(klass,1256,null); 

Nota la modifica a klass, anziché classe, come classe è una parola chiave riservata. Puoi anche usare @class se assolutamente necessario (citandolo).

Se la proprietà è un generico, penso che probabilmente sarà necessario utilizzare Converti per convertire tutto ciò che si ha in qualsiasi cosa sia necessaria.

var nullType = Nullable.GetUnderlyingType(property.PropertyType) 
var value = Convert.ChangeType("1256", nullType); 
property.SetValue(klass, value, null); 
+0

So che è una stringa ma è generica quindi non so quale sarà il tipo. È solo un esempio, la mia genetica Nullable <> potrebbe essere una stringa, int una conversione generica verrà eseguita –

+2

Non è possibile avere un 'Nullable ', poiché 'string' non è un tipo di valore. –

2

"1256" è una stringa, non un int.

5

Ecco un esempio completo che mostra come farlo:

using System; 
using System.Reflection; 

class Test 
{ 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     typeof(Foo).GetProperty("Bar") 
      .SetValue(foo, 1234, null); 
    } 
} 

class Foo 
{ 
    public Nullable<Int32> Bar { get; set; } 
} 

Come altri hanno detto è necessario passare il tipo giusto per la funzione SetValue ma il vostro altro codice di riflessione non è giusto neanche. È necessario ottenere il tipo di classe in questione prima di poter eseguire una query per i suoi membri.

Modifica: Se ho capito correttamente, si sta tentando di impostare un valore stringa su qualsiasi proprietà tramite riflessione. Per fare questo dovrai fare un po 'di ispezione e conversione del tipo.

Ecco un esempio di ciò che intendo:

using System; 
using System.Reflection; 

class Test 
{ 
    static void Main() 
    { 
     Foo foo = new Foo(); 

     PropertyInfo property = typeof(Foo).GetProperty("Bar"); 
     Object value = 
      Convert.ChangeType("1234", 
       Nullable.GetUnderlyingType(property.PropertyType) 
       ?? property.PropertyType); 

     property.SetValue(foo, value, null); 
    } 
} 

class Foo 
{ 
    public Nullable<Int32> Bar { get; set; } 
} 

Questo approccio può essere utilizzato in modo sicuro a prescindere dal fatto che la proprietà è Nullable<>.

2

Ho riscontrato lo stesso problema e un problema con Convert.ChangeType che non gestiva DateTimes su Nullables, quindi ho combinato un paio di soluzioni StackOverflow con alcune funzioni di magia dinamica .NET 4 per ottenere qualcosa che penso sia un po 'dolce. Se si guarda il codice, si usa dynamic per digitare l'oggetto su Nullable in fase di esecuzione, quindi il tempo di esecuzione lo tratta in modo diverso e consente assegnazioni del tipo base all'oggetto nullable.

public void GenericMapField(object targetObj, string fieldName, object fieldValue) 
{ 
    PropertyInfo prop = targetObj.GetType().GetProperty(fieldName); 
    if (prop != null) 
    { 
     if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
     { 
      dynamic objValue = System.Activator.CreateInstance(prop.PropertyType); 
      objValue = fieldValue; 
      prop.SetValue(targetObj, (object)objValue, null); 
     } 
     else 
     { 
      prop.SetValue(targetObj, fieldValue, null); 
     } 
    } 
} 
0
public static void SetValue(object target, string propertyName, object value) 
{ 
    if (target == null) 
    return; 

    PropertyInfo propertyInfo = target.GetType().GetProperty(propertyName); 

    object convertedValue = value; 
    if (value != null && value.GetType() != propertyInfo.PropertyType) 
    { 
    Type propertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; 
    convertedValue = Convert.ChangeType(value, propertyType); 
    } 

    propertyInfo.SetValue(target, convertedValue, null); 
}