2009-11-22 2 views
18

Если свойство определяется следующим образом:.NET Reflection установить частную собственность

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

Как установить его на определенное значение с отражением?

Я попытался как:

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

и

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

, но без какого-либо успеха. Извините, если это глупый вопрос, но это первый раз, когда я использую Reflection с C# .NET.

ответ

34

имеет no setter; вам нужно:

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

(вы, возможно, придется использовать BindingFlags - Постараюсь в минуту)

Без сеттер, вы должны полагаться на модели/имена полей (что хрупкой), или анализировать ИЛ (очень сложно).

Следующие работает отлично:

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

Он также работает с автоматическим Реализуемый собственности:

public DateTime ModifiedOn { get; private set; } 

(где, опираясь на имя-поля нарушило бы ужасно)

+0

Прикольно, не думал о возможности иметь частный в передней части сеттер. И я должен проверить эти BindingFlags, я думаю. Спасибо. –

+4

Похоже, вам нужно только 'BindingFlags', если все свойство является приватным. –

+0

Все еще не работает, поэтому я думаю, мне придется использовать эти BindingFlags? –

2

Если у вашей собственности нет сеттера, вы не можете вызвать SetValue на нем.

3

Вы можете попытаться установить фоновое поле, а не свойство; вы должны использовать GetField() не GetProperty().

+1

Хотя это будет работать, доступ к полям * обычно * является еще более хрупкой формой отражения. Например, что происходит, когда кто-то обнаруживает C# 3.0 и делает это: 'public DateTime ModifiedOn {get; частный набор; } '? –

+0

Если вы * сделаете * хотите установить фоновое поле, чтобы свести к минимуму вероятность нарушения, я попытался бы найти каждую из следующих трех возможностей: (1) То же имя, игорный случай. (2) Подчеркивание + одно и то же имя, игнорируя регистр. (3) Схема именования по умолчанию для поддержки полей авто-свойств (легко найти на SO). – Timo

+0

Обратите внимание, что GetField() имеет перегрузку, которая позволяет IgnoreCase. – Timo

0

Вам нужно установить поле, потому что у вас нет свойства set для установки свойства. Дополнительный BindingFlags.NonPublic необходим для не общедоступных объектов.

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

Если у вас есть частная собственность с установщиком, то вы можете использовать этот метод расширения для установки значения:

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); 
    } 
} 
Смежные вопросы