是否有可能通过反思得到一个房产的私人制定者?

时间:2012-02-09 21:44:09

标签: c# serialization reflection

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

[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。有没有办法访问私有的setter或任何其他方式,以确保只有序列化程序可以访问setter?不保证序列化程序在同一个程序集中。

1 个答案:

答案 0 :(得分:32)

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

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声明Property,而B类通过public new int Property重新声明Property,typeof(B).GetProperty("Property")将返回B中声明的属性,而typeof(A).GetProperty("Property")将返回在A。中声明的财产。