Можно ли получить частный установщик свойства через отражение?

Я написал собственный сериализатор, который работает, устанавливая свойства объекта по отражению. Сериализуемые классы помечены с сериализуемым атрибутом, и все сериализуемые свойства также помечены. Например, следующий класс является сериализуемым:

[Serializable]
public class Foo
{
   [SerializableProperty]
   public string SomethingSerializable {get; set;}

   public string SometthingNotSerializable {get; set;}
}

Когда сериализатор просят десериализовать SomethingSerializable, он получает метод set свойства и использует его для установки, делая что-то вроде этого:

PropertyInfo propertyInfo; //the property info of the property to set
//...//
if (propertyInfo.CanWrite && propertyInfo.GetSetMethod() != null)
{
   propertyInfo.GetSetMethod().Invoke(obj, new object[]{val});
}

Это работает нормально, однако, как я могу сделать установщик свойств доступным только для сериализатора? Если сеттер является частным:

public string SomethingSerializable {get; private set;}

тогда вызов propertyInfo.GetSetMethod() возвращает null в сериализаторе. Есть ли способ получить доступ к частному установщику или любой другой способ гарантировать, что только сериализатор может получить доступ к установщику? Сериализатор не гарантированно находится в одной сборке.

1 ответ

Решение

Как вы уже поняли, один из способов доступа к закрытому сеттеру заключается в следующем:

PropertyInfo property = typeof(Type).GetProperty("Property");
property.DeclaringType.GetProperty("Property");
property.GetSetMethod(true).Invoke(obj, new object[] { value });

Есть и другой способ:

PropertyInfo property = typeof(Type).GetProperty("Property");
property.DeclaringType.GetProperty("Property");
property.SetValue(obj, value, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null);  // If the setter might be public, add the BindingFlags.Public flag.

Приезжаете сюда из поисковика?

Этот вопрос конкретно касается доступа к закрытому сеттеру в публичной собственности.

  • Если и свойство, и setter являются общедоступными, вам подойдет только первый пример. Чтобы второй пример работал, вам нужно добавить BindingFlags.Public флаг.
  • Если свойство объявлено в родительском типе и невидимо для типа, для которого вы вызываете GetProperty вы не сможете получить к нему доступ. Вам нужно будет позвонить GetProperty для типа, которому свойство является видимым. (Это не влияет на частные сеттеры, пока само свойство является видимым.)
  • Если существует несколько объявлений для одного и того же свойства в цепочке наследования (через new Ключевое слово), эти примеры будут нацелены на свойство, которое сразу видно типу, на котором GetProperty называется. Например, если класс A объявляет свойство с помощью public int Property и класс B повторно объявляет свойство через public new int Property, typeof(B).GetProperty("Property") вернет имущество, объявленное в B, а typeof(A).GetProperty("Property") вернет имущество, заявленное в А.
Другие вопросы по тегам