2009-11-22 2 views
18

Se avete una proprietà definita in questo modo:.NET Reflection impostare la proprietà privata

private DateTime modifiedOn; 
public DateTime ModifiedOn 
{ 
    get { return modifiedOn; } 
} 

Come si è impostato per un certo valore con la riflessione?

Ho provato sia:

dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null); 

e

dto.GetType().GetProperty("modifiedOn").SetValue(dto, modifiedOn, null); 

, ma senza alcun successo. Scusa se questa è una domanda stupida, ma è la prima volta che utilizzo Reflection con C# .NET.

risposta

34

che ha nessun setter; avresti bisogno:

public DateTime ModifiedOn 
{ 
    get { return modifiedOn; } 
    private set {modifiedOn = value;} 
} 

(potrebbe essere necessario utilizzare BindingFlags - Cercherò in un attimo)

Senza un setter, che ci si può contare solo su modelli/nomi di campo (che è fragile), o analizzare l'IL (molto difficile).

le seguenti opere di bene:

using System; 
class Test { 
    private DateTime modifiedOn; 
    public DateTime ModifiedOn {  
     get { return modifiedOn; } 
     private set { modifiedOn = value; } 
    } 
} 
static class Program { 
    static void Main() { 
     Test p = new Test(); 
     typeof(Test).GetProperty("ModifiedOn").SetValue(
      p, DateTime.Today, null); 
     Console.WriteLine(p.ModifiedOn); 
    } 
} 

Funziona anche con una proprietà di auto-implementato:

public DateTime ModifiedOn { get; private set; } 

(in cui fare affidamento sul campo-nome si spezzerebbe orribilmente)

+0

fredda, non aveva pensato di essere in grado di avere privato di fronte alla setter. E dovrò controllare quei BindingFlags, credo. Grazie. –

+4

Sembra che tu abbia solo bisogno di "BindingFlags" se l'intera proprietà è privata. –

+0

Ancora non funziona quindi suppongo che dovrò usare quei BindingFlags? –

2

Se la tua proprietà non ha un setter, non puoi chiamare SetValue su di esso.

3

Si potrebbe provare a impostare il campo di supporto e non la proprietà; dovresti usare GetField() non GetProperty().

+1

Mentre funzionerebbe, l'accesso ai campi è * generalmente * una forma di riflessione ancora più fragile. Ad esempio, cosa succede quando qualcuno scopre il C# 3.0 e lo fa: 'public DateTime ModifiedOn {get; set privato; } '? –

+0

Se * si * si desidera impostare il campo di supporto, per ridurre al minimo il rischio di rottura, tenterei di trovare ognuna delle seguenti tre possibilità: (1) Stesso nome, caso igenica. (2) Underscore + stesso nome, ignorando il caso. (3) Schema di denominazione predefinito per i campi di supporto delle proprietà automatiche (facilmente reperibile su SO). – Timo

+0

Si noti che GetField() ha un sovraccarico che consente IgnoraCase. – Timo

0

È necessario impostare il campo perché non è stata impostata alcuna proprietà per impostare la proprietà. Ulteriori informazioni su BindingFlags.NonPublic sono necessarie per oggetti non pubblici.

dto.GetType(). 
    GetField("modifiedOn", 
    BindingFlags.NonPublic|BindingFlags.SetField|BindingFlags.Instance). 
    SetValue(dto, valueToSet); 
0

Se si dispone di una proprietà privata con un setter, allora è possibile utilizzare questo metodo di estensione per impostare un valore:

using System.Reflection; 

public static class ObjectExtensions 
{ 
    public static void SetPrivateValue<T>(this T obj, string propertyName, object value) 
    { 
     var type = typeof(T); 
     type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj, value, null); 
    } 
}