Могу ли я изменить частное унаследованное поле только для чтения в C #, используя отражение? - PullRequest
5 голосов
/ 09 сентября 2009

как в Java у меня есть:

Class.getSuperClass().getDeclaredFields()

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

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

Ответы [ 4 ]

9 голосов
/ 09 сентября 2009

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

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

fi.SetValue(this, 1);

EDIT

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

1 голос
/ 09 сентября 2009

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

Для полей используйте класс 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"
}
1 голос
/ 09 сентября 2009

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

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 голосов
/ 10 сентября 2009

Как предлагает 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);

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

...