Set Object Property Using Reflection

Set object property using reflection

Yes, you can use Type.InvokeMember():

using System.Reflection;
MyObject obj = new MyObject();
obj.GetType().InvokeMember("Name",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, obj, "Value");

This will throw an exception if obj doesn't have a property called Name, or it can't be set.

Another approach is to get the metadata for the property, and then set it. This will allow you to check for the existence of the property, and verify that it can be set:

using System.Reflection;
MyObject obj = new MyObject();
PropertyInfo prop = obj.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
if(null != prop && prop.CanWrite)
{
prop.SetValue(obj, "Value", null);
}

Set property in nested object using reflection

Type.GetGenericArguments() doesn't do anything like what I think you're assuming.

What you want here is recursion. Given ”Foo.Bar[1].Baz”, get Foo. Get Bar[1] from that. Get the PropertyInfo from Baz from its parent, use that to set the value of the Baz property of the Bar[1] property of Foo.

To break it down:

  1. Write a method that "cracks" a property name and uses out parameters to return both the name part and the index value part: "IndexedProperty[1]" goes in; "IndexedProperty" and integer 1 come out. "FooBar" goes in, "FooBar" and null come out. It returns true if there's an indexer, false if not.

    bool CrackPropertyName(string name, out string namePart, out object indexPart)
  2. Write a method that takes an object, and a string "PropertyName" or "IndexedPropety[0]" (not a path -- no dot) and returns the value of that property on that object. It uses CrackPropertyName() to simplify its job.

    object GetPropertyValue(object obj, string name)
  3. Write a method that sets a property value by name (not by path, just by name). Again, it uses CrackPropertyName() to simplify its job.

    void SetPropertyValue(object obj, string name, object newValue)
  4. A recursive method using the above:

    void SetPropertyValueByPath(object obj, string path, object newvalue)
    {
    var pathSegments = /* split path on '.' */;

    if (pathSegments.Length == 1)
    {
    SetPropertyValue(obj, pathSegments[0], newValue);
    }
    else
    {
    // If more than one remaining segment, recurse

    var child = GetNamedPropertyvalue(obj, pathSegments[0]);

    return SetPropertyValueByPath(obj, String.Join(".", pathSegments.Skip(1)), newValue);
    }
    }

These methods are all pretty trivial. Since you're using reflection anyway, you may as well go whole hog and write one non-generic method that sets any property of anything.

Using reflection to set a property of a property of an object

Basically split it into two property accesses. First you get the myClass1Object property, then you set the value property on the result.

Obviously you'll need to take whatever format you've got the property name in and split it out - e.g. by dots. For example, this should do an arbitrary depth of properties:

public void SetProperty(object source, string property, object target)
{
string[] bits = property.Split('.');
for (int i=0; i < bits.Length - 1; i++)
{
PropertyInfo prop = source.GetType().GetProperty(bits[i]);
source = prop.GetValue(source, null);
}
PropertyInfo propertyToSet = source.GetType()
.GetProperty(bits[bits.Length-1]);
propertyToSet.SetValue(source, target, null);
}

Admittedly you'll probably want a bit more error checking than that :)

How to set object property through Reflection

SetValue with Convert.ChangeType should work for you. Using your code:

newValue = Convert.ChangeType(givenValue, prop.PropertyType);
prop.SetValue(target, newValue, null);

Reflections -Set objects property when the property is in a List

You have to get the property value using reflection and change the desired value like this:

var c = new CorePage() { BigLinks = new List<BigLinks> { new BigLinks { TextContent = "Y"}}};
var r = typeof(CorePage).GetProperty("BigLinks").GetGetMethod().Invoke(c, null) as List<BigLinks>;
r[0].TextContent = "X";

If you don't know the type of list item:

var itemInList = (typeof(CorePage).GetProperty("BigLinks").GetGetMethod().Invoke(c, null) as IList)[0];
itemInList.GetType().GetProperty("TextContent").SetValue(itemInList, "XXX", null);

Another option is casting to dynamic:

var itemInList = (typeof(CorePage).GetProperty("BigLinks").GetGetMethod().Invoke(c, null) as dynamic)[0].TextContent = "XXXTTT";

Set property value with reflection

You don’t need to do it that complicated. Once you have extracted the settings object, you can just update that:

PropertyInfo settingsProperty = viewModel.GetType().GetProperty("Settings");
Settings settings = (Settings) settingsProperty.GetValue(viewModel);

settings.A = "Foo";
settings.B = true;
settings.C = 123;

This is already enough to change the settings stored in the view model. If Settings is a value type, you will have to write the changed settings object back to the object, like this:

settingsProperty.SetValue(viewModel, settings);

But that’s really all you will have to do. Of course, if you know that viewModel is of type VM, you can just type-cast it, and access the property directly:

Settings settings = ((VM)viewModel).Settings;

So instead of using reflection, a much better way would be to define some base type, or an interface, that has the Settings property and make your view models implement that:

public interface HasSettings
{
Settings Settings { get; set; }
}

public class VM : HasSettings
{ … }

That way, your method can accept a HasSettings object instead of a plain object, and you can just access the settings object directly:

public void Init (HasSettings viewModel)
{
viewModel.Settings.A = "Foo bar";
}

If you have different Settings types with different properties, and you want to run reflection on those too, then you can do that as well:

PropertyInfo settingsProperty = viewModel.GetType().GetProperty("Settings");
object settings = settingsProperty.GetValue(viewModel);

for (PropertyInfo prop in settings.GetType().GetProperties())
{
object value = GetValueForPropertyName(prop.Name); // magic
prop.SetValue(settings, value);
}

Again, no need to write the settings object back unless it’s a value type.

Setting value of generic property using reflection

In case of arbitrary T you can try Reflection one time more:

      prop.GetType().GetProperty("Value").SetValue(prop, 50);


Related Topics



Leave a reply



Submit