【问题标题】:Why can reflection access protected/private member of class in C#?为什么反射可以访问 C# 中类的受保护/私有成员?
【发布时间】:2011-01-06 06:16:48
【问题描述】:

为什么反射可以访问 C# 中类的受保护/私有成员?

这对班级来说不安全吗,为什么反射被赋予了这样的权力?这是anti-pattern吗?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    反射对于调试器来说是绝对必要的。想象一下,您正在单步执行您的程序并且无法查看私有变量的值。这可能就是反射在 .NET 和 Java 中以它的工作方式工作的原因,使调试变得非常容易。

    如果我们不需要调试器,那么我可以想象,本着OOP 的精神,反射会受到更多限制。

    【讨论】:

    • 调试器不使用反射;调试器直接与 CLR 的特殊调试接口对话。此外,由于调试器是完全受信任的,它可以生成和执行直接访问私有成员的无法验证的代码。
    • 调试器甚至存在于通常没有反射 (C++) 的语言中,并且在二进制应用程序中它直接访问内存偏移量。
    【解决方案2】:

    成员可访问性不是一项安全功能。它可以保护程序员免受他或她自己的伤害。它有助于实现封装,但绝不是安全功能。

    反射使用起来非常乏味,因此人们通常不会特意使用它来访问非公共成员。它也很慢。反射通常只在特殊情况下使用。然而,没有什么可以完全防止人类愚蠢,如果有人想滥用反射,他可以很容易地做到这一点,但即使没有反射 API,他们也可以实现同样的事情(如果他们在完全信任的情况下运行,也就是说)如果他们有足够的决心。

    【讨论】:

      【解决方案3】:

      这对于远程处理、序列化、物化等场景是必要的。您不应盲目使用它,但请注意,这些工具始终在任何系统中都可用(基本上,通过寻址直接记忆)。反射只是将其形式化,并设置控制和检查方式 - 您没有看到,因为您可能在“完全信任”下运行,因此您已经比受保护的系统更强大。

      如果您在部分信任的情况下尝试此操作,您将看到对内部状态的更多控制。

      这是一种反模式吗?

      仅当您的代码使用不当时。例如,考虑以下(对 WCF 数据合同有效):

      [DataMember]
      private int foo;
      
      public int Foo { get {return foo;} set {foo = value;} }
      

      WCF 支持这个不正确吗?我怀疑不是......在多种情况下,您想要序列化不属于公共 API 的内容,而无需单独的 DTO。同样,如果您愿意,LINQ-to-SQL 将具体化为私有成员。

      【讨论】:

      • @Tomas 一种用于在应用程序域之间进行通信的未构建机制。这些可以在进程中,也可以在不同国家/地区的不同机器上。
      • “在多种情况下,您想要序列化不属于公共 API 的内容” - 只有 2 种可能性:API 错误并且应该修复,或者您不必序列化那个“东西”。
      • @TheIncredibleJan 这非常简单。封装的全部目的是隐藏实现细节。但是即使调用者不需要知道它们,你可能仍然需要序列化它们。
      猜你喜欢
      • 2016-07-15
      • 2014-09-14
      • 2012-05-03
      • 2022-07-20
      • 2018-10-21
      • 2016-05-22
      • 2021-06-29
      • 1970-01-01
      • 2014-08-05
      相关资源
      最近更新 更多