zoukankan      html  css  js  c++  java
  • 当扩展方法遇上反射

    类型成员的可访问性(Accessibility)的作用,就是控制类型成员对外的可见性。

    C#支持5种可访问性修饰符:public,private,internal,protected,protected internal,其中protected internal对应于CLR中的Family or Assembly,另外CLR还支持Family and Assembly的可访问性,只是C#不支持。

    反射(Reflection)是一种在运行时提供类型发现和使用的机制,利用反射机制调用类型成员也称为晚期绑定(Late Binding)。

    扩展方法是.Net3.0开始C#编译器提供的语法糖:他允许你定义一个静态方法,并用实例方法的语法调用它。编译器在内部对扩展方法应用ExtensionAttribute特性,这个特性是在System.Core程序集中定义的,所以定义扩展方法需要引用该程序集。

    下面我将通过使用扩展方法和反射演示一种打破对象封装的方法,至少语法看上去如此:)

    首先我构建一个封闭的类Class1

    public sealed class Class1
    {
    private void CallPrivateMethod()
    {
    Console.WriteLine(
    "Private method.");
    }

    public void CallPublicMethod()
    {
    Console.WriteLine(
    "Public method.");
    }
    }

    直接调用Class1.CallPrivateMethod当然会遇到编译错误 CS1061: “Class1”不包含“CallPrivateMethod”的定义,并且找不到可接受类型为“Class1”的第一个参数的扩展方法“CallPrivateMethod”(是否缺少 using 指令或程序集引用?)

    class Program
    {
    static void Main(string[] args)
    {
    var obj
    = new Class1();

    // 可以访问
    obj.CallPublicMethod();

    // 编译错误
    obj.CallPrivateMethod();
    }
    }

    下面是扩展方法,定义扩展方法时务必检查实例是否为Null哦

    public static class Class1Extensions
    {
    private static readonly MethodInfo privateMethod
    = typeof(Class1).GetMethod("CallPrivateMethod"
    BindingFlags.NonPublic | BindingFlags.Instance);

    public static void CallPrivateMethod(this Class1 obj)
    {
    Console.WriteLine(
    "Class1Extensions.CallPrivateMethod");
    if (obj == null)
    {
    throw new NullReferenceException("Class1.CallPrivateMethod");
    }
    privateMethod.Invoke(obj,
    new object[0]);
    }
    }

    这下Main方法可以编译通过了,运行结果:

    Public method.
    Class1Extensions.CallPrivateMethod
    Private method.

    ================================================================

    或许你觉得反射可以很容易绑定并调用一个非公共成员,使得应用程序代码能访问私有成员(就像上文我说的那样)。

    为防止晚期绑定不被滥用,CLR使用代码访问安全性(Code Access Security,CAS)来保证晚期绑定的安全。

    进行晚期绑定时,CAS按下面顺序检查加载程序集权限:

    1.检查成员编译时是否可见,如果可见则绑定成功

    2.查询System.Security.Permissions.ReflectionPermission权限是否设置了ReflectionPermissionFlags.TypeInformation(绑定成员)或ReflectionPermissionFlags.MemberAccess(调用成员)标志,如果有设置则绑定成功

    3.抛出System.Security.SecurityException异常

  • 相关阅读:
    laravel使用redis报错
    PHP新特性W3Cschool
    【python】跳过验证直接登陆-cookie已经知道需要部分直接注入
    【python】显示等待
    【python】pymysql库的简单使用
    【python】UI自动化优化浏览器重复打开和跑脚本时电脑无法做其他工作的问题
    【python】seleniumwire和selenium的区别
    【python】UI自动化-新版
    【python】UI自动化获取输入框的值
    【python】UI自动化多窗口处理
  • 原文地址:https://www.cnblogs.com/neutra/p/1895125.html
Copyright © 2011-2022 走看看