Posso alterar um campo privado readonly herdada em C # usando a reflexão?
-
05-07-2019 - |
Pergunta
como em java eu ??tenho:
Class.getSuperClass().getDeclaredFields()
Como posso saber e definir campo privado de uma superclasse?
Eu sei que isto fortemente não é recomendado, mas eu estou testando meu aplicativo e eu preciso simular uma situação errada, onde o ID está correto e o nome não. Mas isso Id é privado.
Solução
Sim, é possível usar a reflexão para definir o valor de um campo somente leitura após o construtor foi executado
var fi = this.GetType()
.BaseType
.GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
Editar
Atualizado para olhar no tipo de controladora direta. Esta solução provavelmente vai ter problemas se os tipos são genéricos.
Outras dicas
Sim, você pode.
Para os campos, use a classe FieldInfo
. O parâmetro BindingFlags.NonPublic
permite que você veja campos particulares.
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");
}
}
e um pequeno teste para provar que funciona:
public static void Run()
{
var derived = new Derived();
Console.WriteLine(derived.Id); // prints "hi"
derived.changeParentVariable();
Console.WriteLine(derived.Id); // prints "sup"
}
Esta classe vai deixar você fazer isso:
http://csharptest.net/browse/src/Library/Reflection/PropertyType.cs
Uso:
new PropertyType(this.GetType(), "_myParentField").SetValue(this, newValue);
BTW, ele vai trabalhar em campos públicos / não públicos ou propriedades. Para facilidade de uso, você pode usar a classe derivada PropertyValue assim:
new PropertyValue<int>(this, "_myParentField").Value = newValue;
Como JaredPar sugere, eu fiz o seguinte:
//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);
Obrigado a todos.