in my application that uses reflection i have two classes
public class FirstClass
{
public string someVar;
public SecondClass second;
public FirstClass()
{
second = new SecondClass();
}
}
public class SecondClass
{
public string anotherVar;
}
in my main program i have an instance of FirstClass
MainProgram()
{
Object obj = InstanceOfFirstClass() // reflected instance of first class
}
How do i set the value of anotherVar inside obj?
With public fields, this is relatively simple:
object obj = InstanceOfFirstClass();
object second = obj.GetType().GetField("second").GetValue(obj);
second.GetType().GetField("anotherVar").SetValue(second, "newValue");
If the fields were not public, then you would need to use an overload of GetField that takes a BindingFlags argument with the NonPublic flag set.
In .Net 4, you could just use dynamic:
dynamic obj = InstanceOfFirstClass();
obj.second.anotherVar = "newValue";
You can find the example which reads the field and set a value of the field via reflection in
http://msdn.microsoft.com/en-us/library/6z33zd7h.aspx.
In your case it will look like
Object myObject = InstanceOfFirstClass() // reflected instance of first class
Type myType = typeof(FirstClass);
FieldInfo myFieldInfo = myType.GetField("second",
BindingFlags.Public | BindingFlags.Instance);
// Change the field value using the SetValue method.
myFieldInfo.SetValue(myObject , //myobject is the reflected instance
value);//value is the object which u want to assign to the field);
Related
I define a struct:
public struct Settable
{
public string SettableProperty { get; set; }
}
I can set the value of the struct's property in the usual way:
s.SettableProperty = "Abc";
However, when I create a method to attempt to set the property by reflection:
public T CreateWithValue<T>(string propName, string propValue)
{
var retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
var _ = prop.SetMethod.Invoke(retObj, new object[] { propValue});
return retObj;
}
...and call it thus:
var x = CreateWithValue<Settable>("SettableProperty", "Abc");
...I end up with SettableProperty initialized to its default value, null. (No exception is thrown.)
Note that if I define Settable as a class instead of a struct, the value is set as expected.
Is it possible to set struct properties using reflection?
The problem here is that retObj is T, a value-type, but Invoke takes object. This boxes the value, which creates an isolated copy on the heap (inside the box), which you then mutate. Your local copy in retObj isn't impacted in any way here, since it is a completely disconnected copy of the value.
Consider instead:
public T CreateWithValue<T>(string propName, string propValue)
{
object retObj = Activator.CreateInstance<T>();
var prop = typeof(T).GetProperty(propName);
prop.SetMethod.Invoke(retObj, new object[] { typedValue });
return (T)retObj;
}
This creates the box earlier, and unboxes it to get the modified value. It is, however, not very efficient (note: I haven't added any inefficiency; the inefficiency is inherent when using an object API with a value-type). You can remove the allocations if you're happy to get much much dirtier.
I am trying to create a function that can return a field from its object.
Here is what I have so far.
public class Base
{
public string thing = "Thing";
public T GetAttribute<T>(string _name)
{
return (T)typeof(T).GetProperty(_name).GetValue(this, null);
}
}
What I would ideally like is to call:
string thingy = GetAttribute<string>("thing");
but I have a feeling I got the wrong end of the stick when reading up on this because I keep getting null reference exceptions.
First thing - thing is a field, not a property.
Another thing is that you have to change parameter type to get it working:
public class Base {
public string thing = "Thing";
public T GetAttribute<T> ( string _name ) {
return (T)typeof(Base).GetField( _name ).GetValue (this, null);
}
}
BTW - you can get property/field value by referencing an instance:
var instance = new Base();
var value = instance.thing;
thing is a field not a property. You should use GetField method instead of GetProperty.
Another problem is you are looking in typeof(T). You should look for the field in typeof(Base).
The whole function should be changed to
public T GetAttribute<T>(string _name)
{
return (T)GetType().GetField(_name).GetValue(this);
}
If you want to have an extension method to get field value of a type you can use this
public static class Ex
{
public static TFieldType GetFieldValue<TFieldType, TObjectType>(this TObjectType obj, string fieldName)
{
var fieldInfo = obj.GetType().GetField(fieldName,
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic);
return (TFieldType)fieldInfo.GetValue(obj);
}
}
Use it like
var b = new Base();
Console.WriteLine(b.GetFieldValue<string, Base>("thing"));
Using BindingFlags will help you to get field value even if it is private or static field.
SO Community,
So I'm learning C# and am still trying to wrap my head around reflection. In particular trying to use it to access a property of a property on a class.
I've boiled down the basic task that I'm trying to accomplish below:
public enum SIGNAL_STATE { NOT_RETRIEVED = 0, RETRIEVING = 1, RETRIEVED = 2, FAILED = 3 }
public class MyObjectClass
{
public string MyString;
private SIGNAL_STATE _state = SIGNAL_STATE.NOT_RETRIEVED;
public SIGNAL_STATE State { get { return _state; } set { _state = value;} }
}
public class NeedToReflect
{
private MyObjectClass _myObject1 = new MyObjectClass();
private MyObjectClass _myObject2 = new MyObjectClass();
private MyObjectClass _myObject3 = new MyObjectClass();
public MyObjectClass MyObject1
{
get{return _myObject1;}
set{_myObject1 = value;}
}
public MyObjectClass MyObject2
{
get{return _myObject2;}
set{_myObject2 = value;}
}
public MyObjectClass MyObject3
{
get{return _myObject3;}
set{_myObject3 = value;}
}
public static void Main(string [] args){
NeedToReflect needToReflect = new NeedToReflect();
string fieldName;
for(int idx = 1; idx<=3; ++idx)
{
fieldName = String.Format("MyObject{0}",idx);
//TODO: set state of 'MyObject' values to SIGNAL_STATE.RETRIEVING
}
}
}
edit 1:
At Yair Nevet's suggestion I'm grabbing the FieldInfo from the applicable object like,
FieldInfo fieldInfo = needToReflect.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
But from there I get hung up on accessing and setting the right 'State' Field/Property on that member field
Solution (ie. here's what I plugged in on that TODO comment):
// Determine what binding flags will give us proper access to our member field
BindingFlags bindFlags = BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance;
// Get the field for that field
FieldInfo fieldInfo = needToReflect.GetType().GetField(fieldName, bindFlags);
// Pass in the containing object that we're reflecting on to get an instance of the member field
MyObjectClass myField = (MyObjectClass) fieldInfo.GetValue(needToReflect);
// We can now directly access and edit the value in question
myField.State = SIGNAL_STATE.RETRIEVING;
That does it. Thanks to Shlomi Borovitz for pointing me in the right direction.
Thanks!
The FieldInfo object which returned by GetField has property which called FieldInfo, which returns the type of that field.
And you can query it for that type's (the type of the field) properties/fields (and whatever you want) - and get/set them.
Remember that both GetType method (of any object), and the FieldInfo.FieldType property return Type object, that you can query in reflection.
object obj =...
var field = obj.GetType().GetField(fieldName,...);
field.FieldType.GetField(...
//etc... etc...
For each field, you can query the type and for each type, you can query the fields, and get/set them.
BTW, in C# 4.0 you can use the dynamic pseudo type (it used as a type when declaring dynamic variable, but it's not a real type), and then using that variable, while assuming which properties/fields/methods that variable would have in runtime (ie, using them like they are known in compile time although they don't).
This will not work for private members (and I can't warn you enough against calling private members in reflection), but for public members, this would make your code simple and readable, like you never used reflection (although, behind the scenes [in this case] reflection would be used).
You are trying to access a Property while the member is actually a private Field:
propertyName = String.Format("MyObject{0}",idx);
Use GetField method instead for that:
needToReflect.GetType().GetField(propertyName, BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);
Go through these steps...
1) Get the Type.
2) Have an instance of that type.
3) Get the PropertyInfo for the property.
4) Call "GetSetMethod" on the PropertyInfo object. It will return a MethodInfo object.
5) Invoke the MethodInfo object using the instance of the type and a value.
Given:
class ClassyMcClass
{
public int PropertyB { get; set; }
}
class MyClass
{
public ClassyMcClass PropertyA { get; set; }
}
The following code uses reflection on a MyClass object to set the int value of PropertyB in PropertyA to NewValue:
PropertyInfo propA = typeof(MyClass).GetProperty("PropertyA");
PropertyInfo probBofA = propA.PropertyType.GetProperty("PropertyB");
// Set property B of property A, where obj is of type MyClass
probBofA.SetValue(propA.GetValue(obj), NewValue, null);
When I have this property in an abstract class:
public IList<Component> Components { get; private set; }
Then when I call:
p.GetSetMethod(true)
with p being a PropertyInfo object pointing to my property, I get null.
However if I change the property setter to protected, I can see it via reflection. Why is this? I don't seem to recall having this problem with non-abstract classes...
I assume you are calling this on an object from a derived type of your abstract class. There isn't a property setter at all on that class. It is only located on your abstract base. This is why it works when you mark it as protected. You need use your abstract class' Type instead when getting the property setter.
It's an old thread but I run into similar issue recently and none of the above worked for me. Adding my solution as it may be useful for others.
As said before if the setter of a property is private it does not exist in the inherited class. What worked for me was to go one level lower using DeclaringType of the PropertyInfo
So the code to retrieve the property with the setter would look like this:
var propertyInfo = typeof(MyClass)
.GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance)
.DeclaringType
.GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance);
In this case the propertyInfo contains a value for SetMethod so you can set the value using reflection.
Some brief experimentation in the C# Interactive window suggests that for a property P declared on a class A, the following works just fine:
var p = typeof(A).GetProperty("P").GetSetMethod(true)
But as soon as you attempt the same thing with a subclass of A, GetSetMethod no longer resolves the private set accessor:
// class B : A {}
var p = typeof(B).GetProperty("P").GetSetMethod(true) // produces 'null'.
In other words, what you attempted apparently only works for private accessors when the reflected type is the same as the property's declaring type.
The trick is to use the BindingFlags enumeration to specify that you want private members to be included when you obtain the PropertyInfo object:
PropertyInfo p = obj.GetType().GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance);
The following experimentation uncovered the issue for me. Note that the base class doesn't have to be abstract to reproduce the problem.
public class Base
{
public string Something { get; private set; }
}
public class Derived : Base { }
public class MiscTest
{
static void Main( string[] args )
{
var property1 = typeof( Derived ).GetProperty( "Something" );
var setter1 = property1.SetMethod; //null
var property2 = typeof( Base ).GetProperty( "Something" );
var setter2 = property2.SetMethod; //non-null
bool test1 = property1 == property2; //false
bool test2 = property1.DeclaringType == property2.DeclaringType; //true
var solution = property1.DeclaringType.GetProperty( property1.Name );
var setter3 = solution.SetMethod; //non-null
bool test3 = solution == property1; //false
bool test4 = solution == property2; //true
bool test5 = setter3 == setter2; //true
}
}
What I learned from this and found surprising, is that the PropertyInfo on the derived type is a different instance than the PropertyInfo on the base type. Weird!
To build on the work of #piotrwolkowski
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var propertyInfo = typeof(MyClass).GetProperty("Components", flags);
// only go to the declaring type if you need to
if (!propertyInfo.CanWrite)
propertyInfo = propertyInfo.DeclaringType.GetProperty("Components", flags);
I added both public and non-public to the binding flags for my use case (it may be overkill and I don't have the time to pursue it further)
I was setting the instance of an object that inherited from an abstract base with public get and private set
Again, all credit to #piotrwolkowski
I have:
a name of a class field
the class instance that contains the field
The class field 'may' be:
a field I would like to set directly through reflection
a List instance which I would NOT like to set as I don't want to assign a new List instance to it, but instead would like to add to using the 'Add' method.
The problem: I don't have the actual object of the List instance inside the containing object.
Some sample code to illustrate the problem:
class Target
{
FieldInfo m_FieldInfo;
MethodInfo m_MethodInfo;
object m_Target;
public Target( string nameOfTargetField, object containingObject )
{
m_Target = containingObject;
Type type = containingObject.GetType();
BindingFlags bindingFlag = BindingFlags.Public | BindingFlags.Instance;
m_FieldInfo = type.GetField( nameOfTargetField, bindingFlag );
type = m_FieldInfo.FieldType;
m_MethodInfo = type.GetMethod( "Add" );
}
public void Set( object value )
{
if (m_MethodInfo != null) {
object[] parametersArray = new object[] { value };
// This obviously will not work, as m_Target is the containing object,
// no the List<T> instance contained within it:
m_MethodInfo.Invoke( m_Target, parametersArray );
} else if (m_FieldInfo != null) {
m_FieldInfo.SetValue( m_Target, value );
}
}
}
Any suggestions?
Thanks!