2009-11-22 9 views
18

Wenn Sie eine Eigenschaft wie folgt definiert:.NET Reflection gesetzt Privateigentum

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

Wie stellen Sie es auf einen bestimmten Wert mit Reflexion?

Ich habe beide versucht:

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

und

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

aber ohne Erfolg. Entschuldigung, wenn das eine dumme Frage ist, aber es ist das erste Mal, dass ich Reflection mit C# .NET benutze.

Antwort

34

Das hat keine Setter; Sie bräuchten:

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

(Sie BindingFlags verwenden könnte - ich werde in einem Moment versuchen)

Ohne einen Setter, dann würden Sie auf Muster/Feldnamen verlassen müssen (was spröde) oder analysiere die IL (sehr hart).

Folgende Arbeiten fein:

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

Es ist auch mit einer Auto-implementiertes Eigenschaft funktioniert:

public DateTime ModifiedOn { get; private set; } 

(wo auf dem Feldnamen unter Berufung brechen würde schrecklich)

+0

Cool, hatte nicht gedacht vor dem privaten aufweisen können Setter. Und ich werde diese BindingFlags überprüfen müssen. Danke. –

+4

Es sieht so aus, als ob Sie nur 'BindingFlags' benötigen, wenn die gesamte Eigenschaft privat ist. –

+0

Funktioniert immer noch nicht, also werde ich diese BindingFlags verwenden müssen? –

2

Wenn Ihre Eigenschaft hat keinen Setter, Sie können SetValue nicht aufrufen.

3

Sie könnten versuchen, das Hintergrundfeld und nicht die Eigenschaft festzulegen; Sie sollten GetField() nicht GetProperty() verwenden.

+1

Während das funktionieren würde, ist der Zugriff auf Felder * im Allgemeinen * eine noch sprödere Form der Reflexion. Was passiert zum Beispiel, wenn jemand C# 3.0 entdeckt und es macht: 'public DateTime ModifiedOn {get; privates Set; } '? –

+0

Wenn Sie * * * das Hintergrundfeld setzen möchten, um die Wahrscheinlichkeit eines Brechens zu minimieren, würde ich versuchen, jede der folgenden drei Möglichkeiten zu finden: (1) Gleicher Name, Groß-/Kleinschreibung. (2) Unterstrich + gleicher Name, Groß-/Kleinschreibung nicht beachtet. (3) Standardbenennungsschema für die Unterstützung von Feldern von Autoeigenschaften (leicht zu finden auf SO). – Timo

+0

Beachten Sie, dass GetField() eine Überladung aufweist, die IgnoreCase zulässt. – Timo

0

Sie müssen das Feld festlegen, da Sie keine Eigenschaft zum Festlegen der Eigenschaft festgelegt haben. Zusätzlich wird BindingFlags.NonPublic für nicht öffentliche Objekte benötigt.

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

Wenn Sie ein Privateigentum mit einem Setter haben, dann können Sie diese Erweiterung Methode verwenden, um einen Wert zu setzen:

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