C#之属性(attribute)

本文介绍如何在.NET Framework中创建和使用自定义属性,包括定义属性、应用属性及通过反射读取属性值。

属性是.NET Framework最有用的的特性之一,研究它们需要花费大量时间,但是掌握了之后,对我们开发是非常有帮助的

讲之前,大家要知道.net framework属性和C#属性是有区别的哦,不要搞错了.

 

下面我们讲讲它的概念

.net framework属性是一个包含程序集中其他数据的类,这些数据涉及到程序集或程序集中的任何类型.

它的格式大家肯定也不陌生,在项目中的properties文件夹下有个AssemblyInfo.cs

 

ContractedBlock.gifExpandedBlockStart.gifCode
[assembly: AssemblyTitle("BugFix")]
[assembly: AssemblyDescription(
"")]
[assembly: AssemblyConfiguration(
"")]
[assembly: AssemblyCompany(
"Microsoft")]
[assembly: AssemblyProduct(
"BugFix")]
[assembly: AssemblyCopyright(
"Copyright @ Microsoft 2004")]
[assembly: AssemblyTrademark(
"")]
[assembly: AssemblyCulture(
"")]

 

这些就是属性的基本格式了,即用方括号把属性括起来.assembly:标记定义了属性的作用域,其它代码声明了属性,就拿AssemblyTitle属性来说,它有一个构造函数,只有一个参数---字符串值.我们如果要访问这个值的话,可以通过Ildasm查看程序集,或通过"反射"编程访问该值.

说到"反射",也顺带提下吧,反射就是用编程的方式查看程序集,获得程序集的信息,这些信息包含所有对象的类型,用户添加到这些类型中的属性等.用到反射的话,我们要引入System.Reflection这个命名空间.

 

唠叨完属性的基础知识,就进入我们今天的正题--定制属性(就是创建自己的属性).

定制属性分为三个步骤

1.创建一个派生于System.Attribute的类

2.按照需要创建构造函数和公共属性

3.给类添加属性,以定义可以在什么地方使用定制属性

 

下面结合一个实例来讲

首先创建一个控制台应用程序,命名为BugFix

不要忘了引入两个重要的命名空间

using System;
using System.Reflection;

 

接着我们就开始创建自己的属性

ContractedBlock.gifExpandedBlockStart.gifCode
[AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Property 
|
   AttributeTargets.Method 
|
   AttributeTargets.Constructor,
   AllowMultiple 
= true)]
public class BugFixAttribute : Attribute  //定制一个BugFixAttribute属性类
{
    
public BugFixAttribute(string bugNumber, string comments)
    {
        BugNumber 
= bugNumber;
        Comments 
= comments;
    }

    
public readonly string BugNumber;
    
public readonly string Comments;
    
public string Author = null;

    
public override string ToString() //重写ToString()方法
    {
        
if (null == Author)
            
return string.Format("BugFix {0} : {1}", BugNumber, Comments);
        
else
            
return string.Format("BugFix {0} by {1} : {2}", BugNumber, Author, Comments);
    }

    
public static void DisplayFixes(System.Type t)  //静态方法DisplayFix
    {
        
object[] fixes = t.GetCustomAttributes(typeof(BugFixAttribute), false);//反射t中的BugFix属性

        Console.WriteLine(
"Displaying fixes for {0}", t); 

        
foreach (BugFixAttribute bugFix in fixes)  
        {
            Console.WriteLine(
"  {0}", bugFix);
        }

        
foreach (MemberInfo member in t.GetMembers(BindingFlags.Instance |
                                                      BindingFlags.Public 
|
                                                      BindingFlags.NonPublic 
|
                                                      BindingFlags.Static))   
//迭代类上的所有成员,并用BindingFlags枚举限制返回成员列表
        {
            
object[] memberFixes = member.GetCustomAttributes(typeof(BugFixAttribute), false);

            
if (memberFixes.Length > 0)   //如果Bugfix属性数目大于0
            {
                Console.WriteLine(
"  {0}", member.Name);  //输出这些成员

                
foreach (BugFixAttribute memberFix in memberFixes)  
                {
                    Console.WriteLine(
"    {0}", memberFix);
                }
            }
        }
    }
}

我们先是创建了一个BugFixAttribute类,让它继承Attribute类,它的构造函数有两个参数,都是string类型的.为什么这样呢,暂时放一放,呆会下面会提到.然后我们重写了ToString方法,接着就是最重要的一块,用静态方法DisplayFixes()反射BugFix属性

ps:

AttributeUsage:用来定义属性用在什么地方.

AllowMultiple:定义用户是否能给元素添加一个或多个相同的属性

BindingFlags:一个枚举.这里是用来限制返回成员类型的

BugFix属性怎么用呢,可以按照如下方式

 

ContractedBlock.gifExpandedBlockStart.gifCode
[BugFix("101""Created some methods")]
public class MyBuggyCode     //MyBuggyCode类
{
    [BugFix(
"90125""Removed call to base()", Author = "Morgan")]
    
public MyBuggyCode()
    {
    }

    [BugFix(
"2112""Returned a non null string")]
    [BugFix(
"38382""Returned OK")]
    
public string DoSomething()
    {
        
return "OK";
    }
}

 

在第一段代码中,我们讲到BugFixAttribute的构造函数用两个参数,bugNumber即指一个错误号,就是上面的101,90125

而comments就是注释错误的信息.即"Create some methods","Removed call to base"等

 

我们创建DisplayFixes这个静态方法就是为了获取MyBuggyCode这个类的属性

最后通过调用DisplayFixes方法将获取的属性值输出

 

ContractedBlock.gifExpandedBlockStart.gifCode
public class BugRiddenCode
{
    
public static void Main()  //入口函数,调用了DisplayFixes这个静态方法
    {
        BugFixAttribute.DisplayFixes(
typeof(MyBuggyCode));
        Console.ReadKey();
    }
}

 

输出结果如下:

 

ContractedBlock.gifExpandedBlockStart.gifCode
Displaying fixes for MyBuggyCode
 BugFix 
101:Create some methods
 DoSomething
   BugFix 
38382:Returned OK
   BugFix 
2112:Returned a non null string
 .ctor
   BugFix 
90125 by Morgan:Removed call to base() 

 

ps: .ctor是指的构造函数

通过BugFix这个小例子,相信大家对定制属性有所了解

 

后话:

高效的使用属性,可以做很多事情

可以定义程序集的信息,如版权信息啊

可以将代码块标记为过时,以修订程序集

创建自己的属性可以测试代码

我们还可以通过属性生成数据库表等等,虽然可能花费我们大量的时间去研究,但都是值得的,大家有好的例子,不要忘了发出来探讨一下

 

转载于:https://www.cnblogs.com/songzibin/archive/2008/08/20/1272582.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值