一、特性是什么东东
前言我们初学C#的时候看到类上面一对中括号里面有个高亮了的关键字,不知道那是什么有什么用。想问人又不知道它叫什么。纠结的要命。其实,它就是特性。如: 这就是我们今天要分析的主题。 特性是什么?个人理解,特性就是修饰对象元数据的修饰符。 那么什么是“元数据”?元数据就是用来描述数据的数据。
图中的1.是特性 2.是访问修饰符 3.声明修饰符 4.数据类型 5.变量名 6.变量数据值,其中1、2、3、4、5就是元数据,用来描述数据(6)的数据。 特性到底是什么?如上面的??,会不会也是一个如????这样类似的修饰符呢,我们且看看反编译后的中间语言。 意料之外,我们看到了上面的2、3、4、5,而1 然后我们接着在vs里面把光标移到??上按F12,如: 原来只是一个继承了??的一个类?类的实例化了。
我们自定义一个特性玩玩我们看到上面系统特性??上面还有特性,如:Serializable、AttributeUsage、Camvisible等。像这种特性我们称之为“元数据的元数据”(元元数据)。 1.我们分别来解释性上面的三个特性。 Serializable:表示类型支持序列化。 ComVisible:微软定义“控制程序集中个别托管类型、 成员或所有类型对COM的可访问性”。 AttributeUsage:这个比较重要了,基本上每个特性定义都用到了它。它就是用来表示当前这个特性可用于哪些对象。如:类、方法、属性...等等。() 2.上面有个问题,不知道大家发现没有。 就是我们特性名明明是??,为什么我们F12进去后变成了??呢?这其实只是一个微软的约定而已,没有为什么。 其实我们可以两种写法:?)]?和?)]?是等效的,只是我们一般都用后面这种。 3.定义的特性必须继承于??。 4.属性没有set方法。只能通过构造函数赋值。,下面会继续讲到 好了,我们通过这四点完全可以自己定义个特性来玩玩了。我们来定义一个给机器看的注释。我们平时的注释都只是给程序员看的,编译之后就全没了。那我们想在代码运行时,弹出我们的注释怎么办,接下来我们用自定义特性来实现,如: [AttributeUsage(AttributeTargets.All)]
TMessgAttribute : Attribute
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><param name="createTime"></span><span style="color: #008000;">创建时间</span><span style="color: #808080;"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="createName"></span><span style="color: #008000;">创建人</span><span style="color: #808080;"></param></span>
<span style="color: #0000ff;">public</span> TMessgAttribute(<span style="color: #0000ff;">string</span> createTime,<span style="color: #0000ff;">string</span> createName,<span style="color: #0000ff;">string</span><span style="color: #000000;"> mess)
{
</span><span style="color: #0000ff;">this</span>._createName =<span style="color: #000000;"> createName;
</span><span style="color: #0000ff;">this</span>._createTime =<span style="color: #000000;"> createTime;
</span><span style="color: #0000ff;">this</span>._mess =<span style="color: #000000;"> mess;
}
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> _createTime;
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> createTime
{
</span><span style="color: #0000ff;">get</span> { <span style="color: #0000ff;">return</span> _createTime; }<span style="color: #008000;">//</span><span style="color: #008000;">4.只能有get方法</span>
<span style="color: #000000;"> } <span style="color: #0000ff;">public <span style="color: #0000ff;">string<span style="color: #000000;"> createName { <span style="color: #0000ff;">get { <span style="color: #0000ff;">return<span style="color: #000000;"> _createName; } } <span style="color: #0000ff;">private <span style="color: #0000ff;">string<span style="color: #000000;"> _mess; <span style="color: #0000ff;">public <span style="color: #0000ff;">string mess { <span style="color: #0000ff;">get { <span style="color: #0000ff;">return<span style="color: #000000;"> _mess; } } } 好了,上面就是我们自定义的特性。那我们怎样使用呢。和系统特性一样。我们先定义一个测试类TClass,然后在类上面定义特性,如: [TMessg(,,
}
我们定义了特性,也使用了特性,然我们却不知道怎么看效果。我们想看到效果怎么办。可以使用反射看看??类的元数据,如: Main(= (TClass);
TMessgAttribute hobbyAttr = (TMessgAttribute)Attribute.GetCustomAttribute(info,
打印效果如: 什么是命名参数?上面的自定义特性都是通过构造函数设置字段私有字段,然后通过只提供了get的属性来访问。那么可否直接在特性里面定义拥有get和set的属性吗?答案是肯定的。那怎么在使用特性的时候设置这个属性呢?我们接着往下看。 我们接着在自定义特性里面添加一个属性。
modifyTime { ; ; }
使用自定义特性。 [TMessg(,,modifyTime =
}
我们发现,直接在输入了构造函数之后接着设置属性就可以。() 这种参数,我们成为命名参数。 我们来继续要看看AttributeUsage()我们F12看看AttributeUsage的定义 看上去,同样也只是普通的特性。实际上也只是个普通的特性。>_< 我们来看看他的这几个属性是干嘛的。从最后一个开始看。 1.AttributeTargets,我们在上面其实就已经看到并也已经使用了。 我们设置的是可用于所有对象。AttributeTargets其实是个枚举,每个值对于一个类型对象。 你可以直接在??F12进去: 2.Inherited:“” 如下,我们设置??那么继承TClass的T2Class无法访问到TClass中设置的特性元数据。 = )]
TMessgAttribute : Attribute
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><param name="createTime"></span><span style="color: #008000;">创建时间</span><span style="color: #808080;"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="createName"></span><span style="color: #008000;">创建人</span><span style="color: #808080;"></param></span>
<span style="color: #0000ff;">public</span> TMessgAttribute(<span style="color: #0000ff;">string</span> createTime,<span style="color: #0000ff;">string</span><span style="color: #000000;"> mess)
{
</span><span style="color: #0000ff;">this</span>._createName =<span style="color: #000000;"> createName;
</span><span style="color: #0000ff;">this</span>._createTime =<span style="color: #000000;"> createTime;
</span><span style="color: #0000ff;">this</span>._mess =<span style="color: #000000;"> mess;
}
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> _createTime;
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> createTime
{
</span><span style="color: #0000ff;">get</span> { <span style="color: #0000ff;">return</span> _createTime; }<span style="color: #008000;">//</span><span style="color: #008000;">4.只能有get方法</span>
<span style="color: #000000;"> } <span style="color: #0000ff;">public <span style="color: #0000ff;">string<span style="color: #000000;"> createName { <span style="color: #0000ff;">get { <span style="color: #0000ff;">return<span style="color: #000000;"> _createName; } } <span style="color: #0000ff;">private <span style="color: #0000ff;">string<span style="color: #000000;"> _mess; <span style="color: #0000ff;">public <span style="color: #0000ff;">string mess { <span style="color: #0000ff;">get { <span style="color: #0000ff;">return<span style="color: #000000;"> _mess; } } <span style="color: #808080;">/// <span style="color: #808080;"> <span style="color: #808080;">///<span style="color: #008000;"> 修改时间 <span style="color: #808080;">/// <span style="color: #808080;"> <span style="color: #0000ff;">public <span style="color: #0000ff;">string modifyTime { <span style="color: #0000ff;">get; <span style="color: #0000ff;">set<span style="color: #000000;">; } }
<span style="color: #000000;"> }
<span style="color: #000000;"> } 反之,我们设置??()打印如下: 3.AllowMultiple:“” 我们设置两个特性试试,如: 如果我们想要这样设置怎么办。在AttributeUsage中设置??如: 那么上面报错的地方将会打印: 注意:上面的打印地方的代码需要修改。因为之前是打印一个特性信息,这里是打印一个特性数组集合的信息。 Main(= = (TMessgAttribute[])Attribute.GetCustomAttributes(info,(TMessgAttribute));
Console.WriteLine( ( i = ; i < hobbyAttr.Count(); i++)
Console.ReadKey();</span></pre>
全部代码: <span style="color: #0000ff;">namespace<span style="color: #000000;"> net
{ [AttributeUsage(AttributeTargets.All,Inherited = <span style="color: #0000ff;">true,AllowMultiple = <span style="color: #0000ff;">true)]<span style="color: #008000;">//<span style="color: #008000;">3.设置可用于哪些对象 <span style="color: #0000ff;">public <span style="color: #0000ff;">class TMessgAttribute : Attribute<span style="color: #008000;">//<span style="color: #008000;">1.定义类TMessg加上后缀TMessgAttribute 2.继承Attribute。 <span style="color: #000000;"> { <span style="color: #0000ff;">public<span style="color: #000000;"> TMessgAttribute() { }
<span style="color: #000000;"> }
<span style="color: #000000;"> {
<span style="color: #000000;"> }
<span style="color: #000000;"> } 自定义特性可以干什么?上面我们通过反编译,发现自定义特性实际上就是一个对象调用的最前面加了一段实例化的代码。 那么我们可以做的事可多了,除了像上面一样为对象设置“注释”,我们还可以自定义个特性,给某些方法或是某些类做“操作日志记录”,或者给需要在执行某些方法的时候需要权限,我们可以做个权限认证的特性等等。 这里就需要大家自己去扩展了。 本文已同步至《》? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |