当扩展方法遇上反射

巧了我就是萌 提交于 2020-01-05 05:48:31

类型成员的可访问性(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.CallPrivateMethodPrivate method.

 

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

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

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

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

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

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

3.抛出System.Security.SecurityException异常

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!