Можно ли получить частный сеттер свойства через отражение? - PullRequest
21 голосов
/ 10 февраля 2012

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

[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() возвращает нулевое значение в сериализаторе. Есть ли способ получить доступ к частному установщику или любой другой способ гарантировать, что только сериализатор может получить доступ к установщику? Сериализатор не гарантированно находится в одной сборке.

1 Ответ

32 голосов
/ 10 февраля 2012

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

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.

Пришли сюда из поисковика?

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

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