Можно ли получить частный установщик свойства через отражение?
Я написал собственный сериализатор, который работает, устанавливая свойства объекта по отражению. Сериализуемые классы помечены с сериализуемым атрибутом, и все сериализуемые свойства также помечены. Например, следующий класс является сериализуемым:
[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")
вернет имущество, заявленное в А.