.NET Reflection установить частную собственность
Если у вас есть свойство, определенное следующим образом:
private DateTime modifiedOn;
public DateTime ModifiedOn
{
get { return modifiedOn; }
}
Как вы установите его на определенное значение с отражением?
Я пробовал оба:
dto.GetType().GetProperty("ModifiedOn").SetValue(dto, modifiedOn, null);
а также
dto.GetType().GetProperty("modifiedOn").SetValue(dto, modifiedOn, null);
но безуспешно Извините, если это глупый вопрос, но я впервые использую Reflection с C#.NET.
6 ответов
У этого нет сеттера; вам нужно:
public DateTime ModifiedOn
{
get { return modifiedOn; }
private set {modifiedOn = value;}
}
(возможно, вам придется использовать BindingFlags
- попробую через минуту)
Без установщика вам придется полагаться на шаблоны / имена полей (что является хрупким) или анализировать IL (очень сложно).
Следующее работает отлично:
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);
}
}
Он также работает с автоматически реализованным свойством:
public DateTime ModifiedOn { get; private set; }
(где опора на имя поля ужасно сломается)
Вы можете попытаться установить поле поддержки, а не свойство; ты должен использовать GetField()
не GetProperty()
,
Если в вашем свойстве нет сеттера, вы не можете вызвать SetValue.
Вам необходимо установить поле, потому что у вас нет установленного свойства для установки свойства. Дополнительно необходим BindingFlags.NonPublic для непубличных объектов.
dto.GetType().
GetField("modifiedOn",
BindingFlags.NonPublic|BindingFlags.SetField|BindingFlags.Instance).
SetValue(dto, valueToSet);
Если у вас есть частное свойство с установщиком, вы можете использовать этот метод Extension для установки значения:
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);
}
}
Один из способов сделать это, и это, возможно, самый правильный способ, учитывая, что
set
может или не может существовать, заключается в использовании определенного аксессуара
var myc = new MyClass();
var pi = typeof(MyClass).GetProperty("Prop1", BindingFlags.NonPublic | BindingFlags.Instance);
if (pi.SetMethod != null) // check if you have 'set' accessor
pi.SetMethod.Invoke(myc, new object[]{ someValue });
else
{
// do nothing OR
throw new Exception("Attempted to set read-only property " + pi.Name);
}