If you have a property defined like this:
private DateTime modifiedOn;
public DateTime ModifiedOn
{
get { return modifiedOn; }
}
How do you set it to a certain value with Reflection?
I've tried both:
dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null);
and
dto.GetType().GetProperty("modifiedOn").SetValue(dto, modifiedOn, null);
but without any success. Sorry if this is a stupid question but it's the first time I'm using Reflection with C#.NET.
That has no setter; you'd need:
public DateTime ModifiedOn
{
get { return modifiedOn; }
private set {modifiedOn = value;}
}
(you might have to use BindingFlags
- I'll try in a moment)
Without a setter, you'd have to rely on patterns / field names (which is brittle), or parse the IL (very hard).
The following works fine:
using System;
class Test {
private DateTime modifiedOn;
public DateTime ModifiedOn {
get { return modifiedOn; }
private set { modifiedOn = value; }
}
}
static class Program {
static void Main() {
Test p = new Test();
typeof(Test).GetProperty("ModifiedOn").SetValue(
p, DateTime.Today, null);
Console.WriteLine(p.ModifiedOn);
}
}
It also works with an auto-implemented property:
public DateTime ModifiedOn { get; private set; }
(where relying on the field-name would break horribly)
You could try to set the backing field and not the property; you should use GetField()
not GetProperty()
.
If your property doesn't have a setter, you can't call SetValue on it.
You need to set the field because you have no set property to set the property.
Additional the BindingFlags.NonPublic is needed for not public objects.
dto.GetType().
GetField("modifiedOn",
BindingFlags.NonPublic|BindingFlags.SetField|BindingFlags.Instance).
SetValue(dto, valueToSet);
If you have a private property with a setter then you can use this Extension method to set a value:
using System.Reflection;
public static class ObjectExtensions
{
public static void SetPrivateValue<T>(this T obj, string propertyName, object value)
{
var type = typeof(T);
type.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(obj, value, null);
}
}