2009-09-09 1 views
5

как в Java У меня есть:Могу ли я изменить приватное поле, наследуемое только на чтение в C#, используя отражение?

Class.getSuperClass().getDeclaredFields() 

как я могу знать, а частное поле от суперкласса?

Я знаю, что это настоятельно не рекомендуется, но я тестирую свое приложение, и мне нужно смоделировать неправильную ситуацию, когда идентификатор правильный, а имя нет. Но этот идентификатор является конфиденциальным.

ответ

9

Да, можно использовать отражение, чтобы задать значение только для чтения поля после того, как конструктор побежал

var fi = this.GetType() 
      .BaseType 
      .GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic); 

fi.SetValue(this, 1); 

EDIT

Обновлено для просмотра в прямом родительском типе. Это решение, вероятно, будет иметь проблемы, если типы являются общими.

+0

, но с этим кодом я не могу получить родительское поле. хорошо? – Custodio

+0

@ Luís, обновил код, чтобы посмотреть в родительском типе – JaredPar

+0

u теперь почему я только могу получить свое поле, используя « k__BackingField»? – Custodio

1

Этот класс позволит вам сделать это:

http://csharptest.net/browse/src/Library/Reflection/PropertyType.cs

Использование:

new PropertyType(this.GetType(), "_myParentField").SetValue(this, newValue); 

Кстати, она будет работать на общественных/непубличный полей или свойств. Для простоты использования вы можете использовать производный класс PropertyValue так:

new PropertyValue<int>(this, "_myParentField").Value = newValue; 
+0

+1 для библиотеки csharptest-net. У этого есть интересный регистратор. –

1

Да, вы можете.

Для полей используйте класс FieldInfo. Параметр BindingFlags.NonPublic позволяет вам видеть частные поля.

public class Base 
{ 
    private string _id = "hi"; 

    public string Id { get { return _id; } } 
} 

public class Derived : Base 
{ 
    public void changeParentVariable() 
    { 
     FieldInfo fld = typeof(Base).GetField("_id", BindingFlags.Instance | BindingFlags.NonPublic); 
     fld.SetValue(this, "sup"); 
    } 
} 

и небольшой тест, чтобы доказать, что он работает:

public static void Run() 
{ 
    var derived = new Derived(); 
    Console.WriteLine(derived.Id); // prints "hi" 
    derived.changeParentVariable(); 
    Console.WriteLine(derived.Id); // prints "sup" 
} 
0

Как JaredPar предполагает, что я сделал последующие:

//to discover the object type 
Type groupType = _group.GetType(); 
//to discover the parent object type 
Type bType = groupType.BaseType; 
//now I get all field to make sure that I can retrieve the field. 
FieldInfo[] idFromBaseType = bType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); 

//And finally I set the values. (for me, the ID is the first element) 
idFromBaseType[0].SetValue(_group, 1); 

Спасибо всем.

+0

Вы уверены, что idFromBaseType [0] - правильное поле? Вероятно, вы должны соответствовать по имени ... –

+0

Для меня работает, потому что мой первый элемент - это идентификатор. Но я попытался получить поле со строкой, но без успеха. – Custodio

Смежные вопросы