Can I change a private readonly inherited field in C# using reflection? - c#

like in java I have:
Class.getSuperClass().getDeclaredFields()
how I can know and set private field from a superclass?
I know this is strongly not recommended, but I am testing my application and I need simulate a wrong situation where the id is correct and the name not. But this Id is private.

Yes, it is possible to use reflection to set the value of a readonly field after the constructor has run
var fi = this.GetType()
.BaseType
.GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
EDIT
Updated to look in the direct parent type. This solution will likely have issues if the types are generic.

Yes, you can.
For fields, use the FieldInfo class. The BindingFlags.NonPublic parameter allows you to see private fields.
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");
}
}
and a small test to prove it works:
public static void Run()
{
var derived = new Derived();
Console.WriteLine(derived.Id); // prints "hi"
derived.changeParentVariable();
Console.WriteLine(derived.Id); // prints "sup"
}

This class will let you do it:
http://csharptest.net/browse/src/Library/Reflection/PropertyType.cs
Usage:
new PropertyType(this.GetType(), "_myParentField").SetValue(this, newValue);
BTW, It will work on public/non-public fields or properties. For ease of use you can use the derived class PropertyValue like this:
new PropertyValue<int>(this, "_myParentField").Value = newValue;

Like JaredPar suggests, I did the follow:
//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);
Thanks to all.

Related

Get a container class instance from a FieldInfo

I am working with C# reflection here:
I have a FieldInfo of a property and I would like to get the instance of the class it belong (so I can reach the content of another property):
for exemple take this class:
class MyClass
{
public int A { get; set; }
public int B { get; set; }
}
in some part of the code I have
void Function(FieldInfo fieldInfoOfA)
{
// here I need to find the value of B
}
Is this possible ?
Is this possible ?
No. Reflection is about discovery of the metadata of a type. A FieldInfo does not contain any information about a particular instance of that type. This is why you can get a FieldInfo without even creating an instance of the type at all:
typeof(MyClass).GetField(...)
Given the snippet above, you can see that a FieldInfo can be obtained without any dependence on a particular instance.
FieldInfo provides access to the metadata for a field within a class, it is independent of a specified instance.
If you have an instance of MyClass you can do this:
object Function(MyClass obj, FieldInfo fieldInfoOfA)
{
var declaringType = fieldInfoOfA.DeclaringType;
var fieldInfoOfB = declaringType.GetField("B");
return fieldInfoOfB.GetValue(obj);
}

C#: How to extend PropertyInfo?

I have a solution where i get to map out all properties and sub-properties of an object into a Dictionary.
Lets say I have something like these objects:
class MyClassA{
string info;
}
class MyClassB{
string info;
}
class MyClassC{
MyClassA a;
MyClassB b;
string something;
}
class MyClassD{
MyClassC c;
}
I created an utility to map out all the propreties so i can get something like:
MyClassD dObject = Something();
Dictionary<string, PropertyInfo> propertyMap = new Dictionary<string, PropertyInfo>();
propertyMap = buildPropertyMap(dObject );
where the string is the path and the PropertyInfo the actual property. The strings on the Map on this example would look like this (pseudo-output):
propertyMap.Keys={
c;
c.a;
c.b;
c.a.info;
c.b.info;
c.something;
}
This is a great way to tell what goes where when reading for example data from an excel file and not from xml-like things, like so:
ExcelTableC:
-----------------------
1|Ainfo|Binfo|Csomething|
-------------------------
2|value|value|valuevalue|
3|value|value|valuevalue|
-----------------------
It wall works great.
Now thing is, this is all obviously inside a couple of loops and diferent functions (because of the Excel reading process) and i need later to get the key, this is, lets say I have this 'property' and I want the path (dont ask why):
// this method does not exist (pseudo-code)
PropertyInfo.GetPath; //it would return 'c.b.info' for ex. or 'c.a.info'
So i wanted to implement a class that extended PropertyInfo to add my methods.
But doing something like:
public class PropertyField : PropertyInfo
{
PropertyField parent;
string path;
// etc...
}
returns error because PropertyInfo is an abstract class and I would need to implement all inhereted members.
I can add 'abstract' to 'PropertyField' like this:
public abstract class PropertyField : PropertyInfo {}
But then when i try to cast it like this :
private void findProperties(Type objType)
{
PropertyInfo[] properties = objType.GetProperties();
for (int i=0; i< properties.Length; i++)
{
//PropertyInfo propertyInfo = properties[i];
PropertyField property = (PropertyField) properties[i];
//do something with it
}
}
will return the following error:
System.InvalidCastException: Unable to cast object of type
'System.Reflection.RuntimePropertyInfo' to type 'App.models.PropertyField'.
So the question is, how do I add these methods? If I cant inherit what can i do?
You should do:
public class PropertyField
{
PropertyField parent;
string path;
PropertyInfo info;
// etc...
}
I see no point in inheriting PropertyInfo.
Use exstension method to extend the PropertyInfo class instead of inhriting it.
public static class Extensions
{
public static string GetPath(this PropertyInfo pi)
{
// Your implementation to get the path
}
}
The short answer is, better derive from PropertyDescriptor than from PropertyInfo. While the latter is used by the runtime environment and instantiated in RuntimePropertyInfo objects, the latter is used really to meet your purpose, to describe the property. Property descriptors have been used quite a lot in Windows.Forms, basically the whole WinForms designer is built on them and they are quite powerful.
And: you can easily inherit ``PropertyDescriptorand you even do not have to recreate a whole lot of functionality sincePropertyDescriptor` has constructors that allow you to pass in a name and a set of attributes.

How to create a reference to a value-field

Is there a way in C# to create a field which is a reference to another field which is a value type?
class myClass
{
bool b1;
public void method1(ref bool b)
{
b1 = b;
}
}
I want b1 to reference the value of b, just as b references the value of the original argument, so that changes to b1 will affect the original argument.
EDIT:
What I’m trying to achieve is a myCheckBox class which automatically updates a field. See: How do I change a value argument from within an event handler?
Sure! Take a look at Eric's answer to this question:
Setting a ref to a member field in C#
As others have pointed out, you cannot store a reference to a variable
in a field in C#, or indeed, any CLR language.
Of course you can capture a reference to a class instance that
contains a variable easily enough
Well... there is a very contort way :) of course.
That is, using reflection!
You cannot get the address of a field, but we can use reflection.
Reflection is slower than accessing directly a field, i warn you.
And really, accessing private fields of other classes is a really bad practice!
Is however useful sometime for some dirty hacks when you don't have control of code written by other people.
Here the example, but i keep saying, it is not a good practice, is here only for curiosity and for educational purposes!
Fine another way to access your field, using properties or using a class that modify your properties.
// Our FieldReference class that internally uses reflection to get or set a field value.
public class FieldReference<T>
{
private object ownerObject;
private FieldInfo fieldInfo;
public FieldReference(object ownerObject, string fieldName)
{
this.ownerObject = ownerObject;
this.fieldInfo = ownerObject.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
public FieldReference(object ownerObject, FieldInfo fieldInfo)
{
this.ownerObject = ownerObject;
this.fieldInfo = fieldInfo;
}
public T Value
{
get { return (T)this.fieldInfo.GetValue(this.ownerObject); }
set { this.fieldInfo.SetValue(this.ownerObject, value); }
}
}
// Our dummy class
public class MyClass
{
// Our field we want to expose.
private int myField;
public MyClass(int value)
{
this.myField = value;
}
// Just a function we use to print the content of myField.
public override string ToString()
{
return this.myField.ToString();
}
}
class Program
{
public static void Main()
{
// We create our class.
MyClass mc = new MyClass(5);
// We print field value, should be 5 :)
Console.WriteLine(mc.ToString());
// We create our field reference
FieldReference<int> fieldref = new FieldReference<int>(mc, "myField");
// We set the value using field reference.
// Note, we accessed a private field :)
fieldref.Value = 100;
// Now we print the value, should be 100!
Console.WriteLine(mc.ToString());
Console.ReadLine();
}
}
Looks like something that is better solved using delegates/events.
Instead of trying to do the impossible (force value types to behave as reference types), use an event and fire it whenever this value is changed.
Subscribe to this event from the caller/s and you are good to go.
Not knowing what you would want this for you could use a delegate for this, it does sound like a code smell though:
class myClass
{
Action<bool> modify;
public void method1(Action<bool> modify)
{
this.modify = modify;
}
public void ModifyIt()
{
modify(false);
}
}
bool b1 = true; //b1 is true
var m = new myClass();
m.method1(val => { b1 = val; });
m.ModifyIt(); //b1 is false now

How can I reach the "object" behind a property with reflection?

Is there a way to obtain the object behind a property by reflection?
I am trying to manage a dynamic setting of a property.
Example:
class Animal
{
public string Name {get;set;}
public string Family {get;set;}
}
class Zoo
{
public Animal Lion {get;set;}
public Animal Panda {get;set;}
}
class Test
{
public void SetLionNameWithReflection()
{
Zoo londonZoo = new Zoo();
Type zooType = typeof(Zoo);
PropertyInfo lionProperty = zooType.GetProperty("Lion");
// Now what to write here so that I can manage to set Lion's name to Kaspar?
// (to manage this by reflection Lion.Name = "Kaspar");
}
}
What lines should I add more at the commented part above?
Thanks!
I don't think you actually need to know the object behind a property. Use the SetValue method to set its value to "Kaspar":
EDIT - as per dlev's comment, this is how it should look like:
Lion kaspar = new Lion { Name="Kaspar" };
zooType.SetValue(londonZoo, kaspar, null);
A property doesn't necessarily have an object "behind" it.
It's defined by 2 functions, get and set, that can do whatever you want, and not necessarily return an object's value at all.
What you used is just a syntactic sugar to make it easier to make a property to wrap a member.
No you can't use reflection to definitively get the object behind an arbitrary property. Largely because it's not guaranteed that every property is bound to an object. It could just as easily be a calculated value.
public class Student {
public string m_firstName;
public string m_lastName;
public string FullName {
get { return String.Format("{0} {1}", m_firstName, m_lastName); }
}
}
In this case the property FullName produces a calculated value and has no single backing object.
The case you're listing though is for auto-properties. There is likely a way to dig through the fields and use a form of name matching to get the one backing a given auto-property. However such a solution would be fragile to versioning and certainly not recomended.
Can you add an overloaded constructor to your animal object, which will allow you to pass in the animal name, like this?:
londonZoo.GetProperty("Lion").SetValue(londonZoo, new Lion("Kaspar"), null);
First you need to create the lion:
var lion = Activator.CreateInstance(lionProperty.PropertyType);
Then you need to set the Lion property of the zoo:
lionProperty.SetValue(londonZoo, lion, null);
Then you can get the Name property of the lion:
PropertyInfo property = lion.GetType().GetProperty("Name",
BindingFlags.Public | BindingFlags.Instance);
Then you can set its name:
if (property != null && property.CanWrite)
{
property.SetValue(lion, "Kaspar", null);
}

How to get instance from string in C#?

Is it possible to get the property of a class from string and then set a value?
Example:
string s = "label1.text";
string value = "new value";
label1.text = value; <--and some code that makes this
How to do this?
Based this source, the equivalent of
shipment.<propName> = valueToUse,
where 'propName' is the name of the property provided as a string:
using System;
using System.Reflection;
namespace PropertyViaString
{
public class Shipment
{
public string Sender { get; set; }
}
class Program
{
static void Main(string[] args)
{
Shipment shipment = new Shipment();
SetValueExample(shipment, "Sender", "Popeye");
Console.WriteLine("Sender is {0}", shipment.Sender);
Console.ReadKey();
}
static void SetValueExample(Shipment shipment, string propName, string valueToUse)
{
Type type = shipment.GetType();
PropertyInfo senderProperty = type.GetProperty(propName);
senderProperty.SetValue(shipment, valueToUse, null);
}
}
}
prints
Sender is Popeye
You can use reflection to do this, but it will be quite slow?
Perhaps if you tell us what you're trying to achieve by doing this we can help, there are several patterns on event handlers etc. that usually makes this unnecessary.
The answer is use Reflection. However, there are many app frameworks that make the process much easier.
For example, have a look at Spring.Net Expressions. It allows you to do:
ExpressionEvaluator.SetValue(object, "label1", "text");
It is much more powerful and flexible than this simple example, so have a look.
If the given control is an instance variable on your form (if you used the built-in WinForms designer, most are), first get the control, and then set the property on it:
void Form_SetControlProperty(
String controlName, String propertyName, object value)
{
FieldInfo controlField = this.GetType().GetField(controlName,
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
object control = controlField.GetValue(this);
PropertyInfo property = control.GetType().GetProperty(propertyName);
property.SetValue(control, value, new object[0]);
}
You may need to tweak BindingFlags to get this to work.
This must be a method on your form. Call it as:
SetControlProperty("myLabel", "Text", "my label text");
Pay attention to the scope of the method. It any control within the form, but not the form itself (to access the form itself, set control to this).
Note that this uses reflection and will be slow and brittle (change the name of a control and it will break).
You need an instance of the object whose properties you want to set. From your example I'll pretend it is a label.
Label myLabel = new Label();
string s = "text";
string value = "new value";
System.Reflection.PropertyInfo[] properties = myLabel.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo p in properties)
{
if(p.Name == s)
{
p.SetValue(myLabel, value, null);
}
}
I found this code:
Object someObject = myForm; <--- want to make this Object someObject = "myForm";
String propName = "Title";
System.Reflection.PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);
It works. But what to do, that it would by possible to set someObject as a string.
Object someObject = (object)"myForm" <-- this doesn't work.

Categories