Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get a property's private setter through reflection?

I wrote a custom serializer that works by setting object properties by reflection. Serializable classes are tagged with serializable attribute and all serializable properties are also tagged. For example, the following class is serializable:

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

When the serializer is asked to deserialize SomethingSerializable, it gets the set method of the property and uses it to set it by doing something like this:

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

This works fine, however, how can I make the property setter accessible only to the serializer? If the setter is private:

public string SomethingSerializable {get; private set;} 

then the call to propertyInfo.GetSetMethod() returns null in the serializer. Is there any way to access the private setter or any other way to ensure that only the serializer can access the setter? The serializer is not guaranteed to be in the same assembly.

like image 851
Rado Avatar asked Feb 09 '12 21:02

Rado


People also ask

What is a private setter?

private setters are same as read-only fields. They can only be set in constructor. If you try to set from outside you get compile time error. public class MyClass { public MyClass() { // Set the private property.

What is C# reflection?

Reflection provides objects (of type Type) that describe assemblies, modules, and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.


1 Answers

As you already figured out, one way to access a non-public setter is as follows:

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

There is another way, though:

PropertyInfo property = typeof(Type).GetProperty("Property"); // if Property is defined by a base class of Type, SetValue throws 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. 

Coming here from a search engine?

This question is specifically about accessing a non-public setter in a public property.

  • If both the property and setter are public, only the first example will work for you. To get the second example to work, you will need to add the BindingFlags.Public flag.
  • If the property is declared in a parent type and not visible to the type on which you're calling GetProperty, you won't be able to access it. You'll need to call GetProperty on a type to which the property is visible. (This doesn't affect private setters as long as the property itself is visible.)
  • If there are multiple declarations for the same property in the inheritance chain (via the new keyword), these examples will target the property that is immediately visible to the type on which GetProperty is called. For example, if class A declares Property using public int Property, and class B re-declares Property via public new int Property, typeof(B).GetProperty("Property") will return the property declared in B, while typeof(A).GetProperty("Property") will return the property declared in A.
like image 100
Zenexer Avatar answered Oct 02 '22 23:10

Zenexer