由 EditorBrowableAttribute 引发的一些问题

来源:互联网 发布:免费的收音机不用网络 编辑:程序博客网 时间:2024/05/22 03:19

     作为一个程序员,相信大家对"智能感知"(Intellisense)一定不会感到陌生,甚至可以夸张的说:正是由于智能感知功能的存在,才让面对对象的编程思想变的如此普及。

      当然,再好功能也有办坏事的时候,智能感知功能也不例外。在 Visual Stuido 系列中进行基于 .NET 的开发时,由于所有的类都继承于 Object 类,导致我们在访问任何类的成员列表时, GetType、ToString、GetHashCode 等几个 Object 的成员都被"智能"的加进了提示列表中。这显示不是我们所需要的,有没有办法可以把他们屏蔽掉呢?本人尝试着 Google 一下,并有幸的在 Anytao 的博客 中找到了解决方法,那就是使用 EditBrowableAttribute 这个属性类。

EditBrowsableAttribute 的使用其实很简单,我们先做一个示例:

代码

      在新建项目中引用该类,我们激活智能提示:,

PNG_1
      正如我们希望的,语句[EditorBrowsable(EditorBrowsableState.Never)] 正常工作并在智能提示中屏蔽了Hide方法的显示;那么如何屏蔽 Object 类的方法呢?很简单,重写这些方法并使用 EditBrowableAttribute 属性将他们一一屏蔽就行了:

代码

    一切跟我们预料的一样,智能提示中只剩下了我们希望保留的 Show 方法。

PNG_2
    本来问题到这里就应该结束了,但是回顾一下 Anytao 的样例,却发现作者在样例中拐了几个弯才实现屏蔽效果,整理一下,大致实现手段如下:

  1. 定义一个 IAnyObject 接口,在接口中使用 EditBrowableAttribute 属性来屏蔽 Object 类的四个方法;
  2. 定义一个 IObject 接口,该接口继承于 IAnyObject 接口,并声明最终类的所有成员。
  3. 使用 IObject 接口类型的变量来操作最终实现类 AnyObject 的实例;

    为什么作者要这么做?作者很聪明,他通过一个 IAnyObject 接口来简化以后所有需要对 Object 成员进行屏蔽的操作;但是事情显然还不是那么简单,至少对本人来说,示例中的代码透漏出几点诡异之处:

  1. 为什么要定义 IObject 接口,而不是直接将 AnyObject 类继承于 IAnyObject 接口;
  2. 为什么必须通过 IObject 接口类型的变量来操作 AnyObject 类的实例;为什么直接声明 AnyObject 类型的变量不能实现屏蔽效果;
  3. 为什么在 AnyObject 类的实现代码中没有提供 IAnyObject 接口声明的方法;

    为了让自己把事情完全搞明白,本人开始尝试做一些实现。首先,定义一个接口,在接口中定义一个屏蔽显示的方法,然后在最终的类中实现该方法。如下:

代码

     结果很明显,智能感知对 EditorBrowsableAttribute 属性的识别是在变量所属类型的定义中查找的。对于一个 TestClassC 的实例,如果使用 TestClassC 类型的变量操作,Hide 方法出现在智能提示中。如果使用 IInterface 类型的变量中操作,Hide 方法不出现在智能提示中;

     在前面实验的基础上继续思考,如果方法在父类中实现并屏蔽,子类中没有实现呢?或者在父类中屏蔽,在子类中重写但没有明确屏蔽呢?继续实验:

代码


      这下就完全清晰了。在 SubClassA 类型的变量中,Hide方法使用了父类中的屏蔽声明,没有出现在智能提示中,而重写的 VirtualHide 方法显示在智能提示中,虽然子类中没有明确的加入[EditorBrowsable(EditorBrowsableState.Always)] 声明,但是父类中的隐藏声明已经明显无效了。

      关于 EditorBrowsableAttrbute 属性类如何工作已经明确了,但是还有一个问题,为什么类继承接口时没有实现接口的成员方法?就因为父类已经实现过一个声明方式一样的方法吗?继续实验:

代码

 

     代码被准确无误的编译通过并成功执行。原来这样也行,那基于适配器模式(Adapter Pattern)的编写岂不是可以简化很多了。假设以前供应商、销售商两个独立的类

 
代码

现在需要为两个类编写一个通用的接口来共同操作,按照以前对适配器模式的理解,代码应该这样写

 

代码


由于接口中定义的方法只要父类中已经实现就不需要在最终类中重新实现,简化后的代码可以这样写:

 

代码

简单的做一下继承就可以了,好简单。

原创粉丝点击