业务应该这么写--特性
特性真的好常见,用到地方也挺多的。
在我平时工作中,看得比较多的特性有Web端:权限控制Authorize,过滤器,序列化,WCF,Webservice里面也有很多,WebMethod,DataContract,还有做桌面端的用得最多的DllImport(可以直接和Win32程序进行通信),还有我们常用到ORM,特性真的是无所不能,好像高逼格的地方,特性总是要来搞事。下面让我们一起来看看特性究竟是怎么样进行工作的。
(一)特性出现的背景和初衷是什么,用来解决什么问题
特性:给类,方法等提供附加的功能,增强了软件系统的灵活性,促进了功能的松散耦合。
用特性呢,可以避免多个类似的代码段,创建更为可读和清晰的代码。如果我们可以用.Net自带的特性,我们应该积极的用。
如果不能的话呢,我们就可以自己定义一个特性类。特性属于声明式编程的一种。
(二)特性的好处和坏处,带来的挑战是什么
特性的好处:在不破坏类型封装的前提下,增加一点额外的信息和功能。更加灵活了。就是可以把业务和非业务逻辑区分得更开。
特性的坏处:定义。应用和反射特性能带来许多便利。所以很多开发人员都喜欢用这些技术。而特性是存在元数据里面的,可能会对性能有一些影响。因为要用反射的话,内部都必须扫描托管模块的元数据,执行字符串比较来定位到指定的特性类。这样操作是会耗费一定时间的。
假如对性能要求比较高的话,可以缓存这些结果。
(三)适用场景
1、业务场景
我们平时很多公共逻辑,比如需要登录才可以进行授权。定义枚举的时候,要带上描述信息。ORM里面的表名,列名映射关系。等等,还有很多地方,欢迎大家补充。
(四)特性的组成部分和关键点
4/1 特性的基本组成
从上图可以知道,特性是属于元数据里面的内容的,我们也可以通过反编译来看看一下就可以明白了。
1、如下例子:
class Program { [Text()] static void Main(string[] args) { Console.WriteLine("test"); } } public class TextAttribute : Attribute { }
我们直接来看反编译这段程序之后的IL;
从上面可以看出,特性就是存在我们元数据中的,而且还会去调用这个特性类的构造函数。
4/2 特性的基础知识点
1、特性类,都必须要继承自Attribute。这是因为面向CLR的所有编译器都必须识别Attribute,并且最终能在元数据中生成特性信息。
编译器有点傻的就是不管这个特性有没有用,都会生成对应的元数据。
2、特性可以应用于程序集,模块,类型,字段,返回值,方法,参数,属性,事件。
3、接下来我们思考一个问题,我们是不是定义一个特性,然后就可以随便用呢,用在属性,方法,程序集,等等这些属性上。假如我们不指定特性的使用范围呢,那我们反射的时候,是不是要从方法,属性,类上面都检测一下是否含有这个特性呢,想想这样会给我们性能带来多大的影响呢。所以C#的设计者给我们提供了一个 [AttributeUsage(AttributeTargets.All,AllowMultiple =true,Inherited =true)] 这个东西。
(1)AttributeUsage是一个特性类,可以通过reflector看看它里面就明白了
我们直接需要传三个参数的构造函数。 [AttributeUsage(AttributeTargets.All,AllowMultiple =true)]
AttributeTargets 这是一个枚举。这个主要是用来指定特性的作用范围。作为一个程序员,我们应该要根据需要来合理指定。
Inherited: 这个是说这个特性是否要进行继承,如果要设置为true的话呢,我们反射去检查它的派生类是否应用了这个特性。
一般情况下,我们不会把这个值设置为true,这样除了会额外的检查,可能还会带来混淆。所以一般建议定义特性类的时候,把它
设定为sealed,减少混淆,避免这次检查。
AllowMultiple:一般来说,太多特性多次应用于同一个目标是没有意义的。没有什么特别必要把这个值设置为true。
4/3 特性的三部曲。
1、定义一个类,继承自Attribute类,并且类名是以Attribute结尾的。
2、给指定的方法,属性,类等等,给需要用特性的地方,加上特性打上标记。
3、通过反射来调用,使得特性生效。
很多人的错觉,就是以为写上特性就可以生效。所有让特性生效的地方一定是主动应用了这个特性。
(五)特性的底层原理和关键实现
定制特性能有效,完全是因为元数据和反射这个东东。
(六)已有的实现和它进行对比
之前我们没用特性的时候,我们普通的做法就是,假设现在是做Webservice开发,定义一个父类(Base),里面写一些通用的方法,然后所有的asmx都继承这个父类,之后在每个需要用的地方调用一下。
估计还有其他做法,我之后再慢慢分享,今天实在是太累了...欢迎大家留言讨论,祝大家中秋快乐。