是否可以通过反射获得属性的私有 setter? [英] Is it possible to get a property's private setter through reflection?

查看:25
本文介绍了是否可以通过反射获得属性的私有 setter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个自定义序列化程序,它通过反射设置对象属性来工作.可序列化的类用可序列化的属性标记,所有可序列化的属性也被标记.例如,以下类是可序列化的:

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;}
}

当序列化器被要求反序列化 SomethingSerializable 时,它获取属性的 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});
}

这很好用,但是,如何使属性设置器只能由序列化程序访问?如果 setter 是私有的:

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;}

然后对 propertyInfo.GetSetMethod() 的调用在序列化程序中返回 null.有没有办法访问私有 setter 或任何其他方式来确保只有序列化程序可以访问 setter?不保证序列化程序在同一个程序集中.

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.

推荐答案

正如您已经想到的,访问非公共 setter 的一种方法如下:

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.

从搜索引擎来到这里?

这个问题专门关于访问公共属性中的非公共 setter.

Coming here from a search engine?

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

  • 如果属性和 setter 都是公开的,则只有第一个示例适合您.要使第二个示例工作,您需要添加 BindingFlags.Public 标志.
  • 如果该属性在父类型中声明并且对您调用 GetProperty 的类型不可见,您将无法访问它.您需要对属性可见的类型调用 GetProperty.(只要属性本身可见,这不会影响私有 setter.)
  • 如果继承链中的同一属性有多个声明(通过 new 关键字),这些示例将针对 GetProperty<所在的类型立即可见的属性./code> 被调用.例如,如果A类使用public int Property声明了Property,B类通过public new int Property重新声明了Property,typeof(B).GetProperty(Property") 将返回 B 中声明的属性,而 typeof(A).GetProperty(Property") 将返回 A 中声明的属性.
  • 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.

这篇关于是否可以通过反射获得属性的私有 setter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆