2009-11-22 4 views
18

Si vous avez une propriété définie comme ceci:réflexion .NET set propriété privée

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

Comment définissez-vous à une certaine valeur avec la réflexion?

J'ai essayé à la fois:

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

et

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

mais sans aucun succès. Désolé si c'est une question stupide mais c'est la première fois que j'utilise Reflection avec C# .NET.

Répondre

34

a aucun paramètre; vous auriez besoin:

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

(vous pourriez avoir à utiliser BindingFlags - Je vais essayer dans un instant)

Sans un poseur, vous auriez à appuyer sur les modèles/noms de champ (ce qui est fragile), ou analyser l'IL (très dur).

Les travaux suivants fins:

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

Il fonctionne également avec une propriété implémentée automatiquement:

public DateTime ModifiedOn { get; private set; } 

(où se fondant sur le nom du champ briserait horriblement)

+0

Cool, n'avait pas pensé à être en mesure d'avoir privé devant la setter. Et je vais devoir vérifier ces BindingFlags je suppose. THX. –

+4

Il semblerait que vous ayez seulement besoin de 'BindingFlags' si la propriété entière est privée. –

+0

Cela ne fonctionne toujours pas, donc je suppose que je vais devoir utiliser ces BindingFlags? –

2

Si votre propriété n'a pas de setter, vous ne pouvez pas appeler SetValue dessus.

3

Vous pouvez essayer de définir le champ de support et non la propriété; vous devez utiliser GetField() et non GetProperty().

+1

Bien que cela fonctionne, l'accès aux champs est * généralement * une forme de réflexion encore plus fragile. Par exemple, que se passe-t-il lorsque quelqu'un découvre C# 3.0 et le fait: 'public DateTime ModifiedOn {get; ensemble privé; } '? –

+0

Si vous voulez * définir * le champ de sauvegarde, afin de minimiser les risques de rupture, j'essaierais de trouver chacune des trois possibilités suivantes: (1) Même nom, cas d'igoring. (2) Underscore + même nom, en ignorant le cas. (3) Schéma de nommage par défaut pour les champs de sauvegarde des auto-propriétés (facilement trouvé sur SO). – Timo

+0

Notez que GetField() a une surcharge qui autorise IgnoreCase. – Timo

0

Vous devez définir le champ car vous n'avez aucune propriété set pour définir la propriété. Le BindingFlags.NonPublic supplémentaire est nécessaire pour les objets non publics.

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

Si vous avez une propriété privée avec un setter, vous pouvez utiliser cette méthode d'extension pour définir une valeur:

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