2009-11-22 25 views
18

Si usted tiene una propiedad definida así:.NET de Reflexión propiedad privada

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

¿Cómo se establece en un valor determinado con la reflexión?

He intentado tanto:

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

y

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

pero sin ningún éxito. Lo siento si esta es una pregunta estúpida, pero es la primera vez que uso Reflection with C# .NET.

Respuesta

34

Eso tiene no setter; se necesitaría:

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

(puede que tenga que utilizar BindingFlags - Voy a tratar en un momento)

Sin un organismo, que tendría que depender de los patrones/nombres de campo (que es frágil), o analizar el IL (muy difícil).

Los siguientes trabajos finos:

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

También funciona con una propiedad de auto-aplicado:

public DateTime ModifiedOn { get; private set; } 

(donde confiar en el nombre de campo se rompería horrible)

+0

fresca, no había pensado en ser capaz de tener privada frente a la setter. Y tendré que comprobar esos BindingFlags, supongo. Gracias. –

+4

Parece que solo necesita 'BindingFlags' si toda la propiedad es privada. –

+0

Todavía no funciona, así que supongo que tendré que usar esos BindingFlags? –

2

Si su propiedad no tiene un colocador, no puede llamar a SetValue en él.

3

Puede intentar establecer el campo de respaldo y no la propiedad; debe usar GetField() no GetProperty().

+1

Si bien eso funcionaría, acceder a los campos es * generalmente * una forma de reflexión aún más frágil. Por ejemplo, qué sucede cuando alguien descubre C# 3.0 y lo hace: 'public DateTime ModifiedOn {get; conjunto privado; } '? –

+0

Si * desea * establecer el campo de respaldo, para minimizar la posibilidad de quebrarse, trataré de encontrar cada una de las tres posibilidades siguientes: (1) Mismo nombre, ignorando el caso. (2) subrayado + mismo nombre, ignorando mayúsculas y minúsculas. (3) Esquema de denominación predeterminado para respaldar campos de propiedades automáticas (se encuentra fácilmente en SO). – Timo

+0

Tenga en cuenta que GetField() tiene una sobrecarga que permite IgnoreCase. – Timo

0

Debe establecer el campo porque no tiene una propiedad establecida para establecer la propiedad. Además, se necesita BindingFlags.NonPublic para objetos no públicos.

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

Si usted tiene una propiedad privada con un regulador, puede utilizar este método de extensión para establecer un valor:

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