Reputation: 57
I have to set a property inside an unknown object. The structure looks like this:
ObjA.ObjB().ObjC.PropA = propValue;
ObjA is from a referenced class. ObjB() is of type object and therefore ObjC is unknown. I thought about using Reflection but don't know how to use it correctly in this case.
object objB = ObjA.ObjB();
Type objBType = objB.GetType();
System.Reflection.XXXInfo objCInfo = objBType.GetXXX("ObjC");
Type objCType = objCInfo.GetType();
System.Reflection.PropertyInfo PropAInfo = objCType.GetProperty("PropA");
PropAInfo.SetValue(PropAInfo, propValue, null);
Answer (Thanks to BigM):
dynamic objAB = ObjA.ObjB();
objAB.ObjC.PropA = propValue;
Upvotes: 2
Views: 5100
Reputation: 18102
Here are a couple of generic extension methods to help you get and set "unknown" properties by name:
public static class ReflectionHelpers
{
public static bool TrySetProperty<TValue>(this object obj, string propertyName, TValue value)
{
var property = obj.GetType()
.GetProperties()
.Where(p => p.CanWrite && p.PropertyType == typeof(TValue))
.FirstOrDefault(p => p.Name == propertyName);
if (property == null)
{
return false;
}
property.SetValue(obj, value);
return true;
}
public static bool TryGetPropertyValue<TProperty>(this object obj, string propertyName, out TProperty value)
{
var property = obj.GetType()
.GetProperties()
.Where(p => p.CanRead && p.PropertyType == typeof(TProperty))
.FirstOrDefault(p => p.Name == propertyName);
if (property == null)
{
value = default(TProperty);
return false;
}
value = (TProperty) property.GetValue(obj);
return true;
}
}
And a usage example:
public class Program
{
public static void Main()
{
var foo = new Foo
{
Bar = new Bar
{
HelloReflection = "Testing"
}
};
string currentValue;
if (foo.Bar.TryGetPropertyValue("HelloReflection", out currentValue))
{
Console.WriteLine(currentValue); // "Testing"
}
if (foo.Bar.TrySetProperty("HelloReflection", "123..."))
{
foo.Bar.TryGetPropertyValue("HelloReflection", out currentValue)
Console.WriteLine(currentValue); // "123.."
}
else
{
Console.WriteLine("Failed to set value");
}
}
}
public class Foo
{
public object Bar { get; set; }
}
public class Bar
{
public string HelloReflection { get; set; }
}
Upvotes: 2
Reputation: 67898
This should probably work for you.
object objB = ObjA.ObjB();
Type objBType = objB.GetType();
System.Reflection.PropertyInfo objCInfo = objBType.GetProperty("ObjC");
object val = objCInfo.GetValue(objB);
Type objCType = val.GetType();
System.Reflection.PropertyInfo PropAInfo = objCType.GetProperty("PropA");
PropAInfo.SetValue(val, propValue, null);
However, I think a bit of re-architecting could be done here to make life a bit easier. For example, if you don't know anything about the types then you might consider using dynamic
and returning dynamic
types from ObjC
and PropA
- but there is a performance hit there.
On the other hand, if there is any way that you can use generics, that would make your life a lot easier. For example, the code here that sets the property value, if that method were generic it might likely be able to define the type of ObjC
- but I can't really infer that with the current snippet.
Upvotes: 2