Setting a Property by Reflection With a String Value

Setting a property by reflection with a string value

You can use Convert.ChangeType() - It allows you to use runtime information on any IConvertible type to change representation formats. Not all conversions are possible, though, and you may need to write special case logic if you want to support conversions from types that are not IConvertible.

The corresponding code (without exception handling or special case logic) would be:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

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);
}

Get property value from string using reflection


 public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}

Of course, you will want to add validation and whatnot, but that is the gist of it.

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.

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 :)

Reflection: Get/Set Value of Property's PropertyType's Property

Modified your code, sure I have no running code but concept should be clear to you:

public void insertAllFromVariable(GameObject target, List<Type> types, string propertyName)
{
var components = target.GetComponents<Component>();
foreach (var component in components)
{
if (types.Contains(component.GetType()))
{
PropertyInfo property = component.GetType().GetProperty(propertyName);
object theRealObject = property.GetValue(component);

PropertyInfo[] propertysProperties = theRealObject.GetType().GetProperties().Where(t => t.GetCustomAttributes<ListableAttribute>().Count() > 0);
foreach (PropertyInfo p in propertysProperties)
{
Debug.Log("VALUE: " + p.GetValue(theRealObject));

C# Reflection - SetValue by path to property

I think your original version will end up setting the value "one level too deep".

I think a recursive pattern would be easier to follow, and require less code. Here is a quick version that I threw together that works on simple test cases.

There are several opportunities for optimizations (rebuilding the string on the recursive call), and edge cases (like null checks) that I don't have the time to handle right now, but I don't think they will be too hard to add.

public void SetProperty(object target, string property, object setTo)
{
var parts = property.Split('.');
var prop = target.GetType().GetProperty(parts[0]);
if (parts.Length == 1)
{
// last property
prop.SetValue(target, setTo, null);
}
else
{
// Not at the end, go recursive
var value = prop.GetValue(target);
SetProperty(value, string.Join(".", parts.Skip(1)), setTo);
}
}

Here is a LINQPad demo showing it in action:

void Main()
{
var value = new A();
Debug.WriteLine("Original value:");
value.Dump();

Debug.WriteLine("Changed value:");
SetProperty(value, "B.C.D","changed!");
value.Dump();
}

public void SetProperty(object target, string property, object setTo)
{...}

public class A
{
public B B { get; set; } = new B();
}

public class B
{
public C C { get; set; } = new C();
}

public class C
{
public string D { get; set; } = "test";
}

It produces the following results:

Sample Image

Change property value

replace this code :

you should pass instance of object to getValue() or setValue() not property

public static T LocalTime<T>(T value, string locationTimeZone)
{

if (value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition() == typeof(List<>))
{

IList collection = (IList)value;
foreach (var element in collection)
{
PropertyInfo[] props = element.GetType().GetProperties();
foreach (var property in props)
{
if (property.PropertyType == typeof(System.DateTime?))
{
var localTime = LocalTimeConvert("Alaskan Standard Time", DateTime.Now);
property.SetValue(element, localTime);
}
else if (property.PropertyType == typeof(System.DateTime))
{
property.SetValue(element, ((System.DateTime)property.GetValue(element, null)).AddDays(10), null);
}
}
}
}
return value;
}

Cast a value and set a property using reflection

See SetValue method. You should swap value and object parameters:

_propertyInfo.SetValue(Element, value, null);  

How get inner property value by reflection

Instead of using var, you can force the type of aa to be a dynamic.

dynamic aa = propertyInfo.GetValue(Rating, null);
return aa.from;


Related Topics



Leave a reply



Submit