一、属性的基本概念
1、什么是属性?为什么要使用属性?
属性提供功能强大的方法以将声明信息与 C# 代码(类型、方法、属性等)相关联。特别在数据库设计中,一个数据库中的各个字段的性质不一样,有的是primary key,有的是key,有的则是普通的字段,通过属性的该表的类中进行字段标识,使用时通过反射出这些属性就可以知道这个字段的信息。
2、属性的两种表现形式
一种是在公共语言运行时 (CLR) 中定义的属性。
另一种是可以创建的用于向代码中添加附加信息的自定义属性。此信息可在以后以编程方式检索。
3、属性的使用场合
属性可以放置在几乎所有的声明中(但特定的属性可能限制在其上有效的声明类型)。
4、属性的使用语法
在语法上,属性的指定方法为:将括在方括号中的属性名置于其适用的实体声明之前。
二、属性的案例说明
本案例主要实现自定义属性类DescriptionAttribute,在类CNBAStar及其成员中应用该属性,并在main()中通过反射的方式将这些属性获取。
案例代码:
点击(此处)折叠或打开
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
-
- namespace CustomAttibute2
- {
- class Program
- {
- [Description("I'm class CNBAStar ",ExtraInfo="private")]
- class CNBAStar
- {
- private string mName = "Michael Jordan";
-
- #region Properties field
- [Description("I'm CNBAStar's attribute Name")]
- public string Name
- {
- get { return mName; }
- set { Name = mName; }
- }
- #endregion
-
- #region Methods field
- [Description("I'm CNBAStar's mothed ShowTime()",ExtraInfo="public")]
- public string ShowTime()
- { return mName + " is most famous basketball player of the world!"; }
-
- [method: Description("I'm CNBAStar's mothed ShowTime2()")]
- public string ShowTime2()
- { return "Kobe Brynt is so so."; }
-
- [return: Description("Just mark the return value of showTime3() ")]
- public string ShowTime3()
- { return "Lebron James is so so."; }
- #endregion
- }
-
- static void Main(string[] args)
- {
- /* 反射出CNBAStar class中携带信息的方法 */
- Object[] attrs = typeof(CNBAStar).GetCustomAttributes(true);
- foreach (Object obj in attrs)
- {
- if (obj is DescriptionAttribute)
- {
- Console.WriteLine((obj as DescriptionAttribute).MData);
- Console.WriteLine("===================================================");
- }
- }
-
- /* 反射出CNBAStar class中相关属性、方法所携带信息的方法:
- * 先获取class.members,再取type.GetCustomAttributes() */
- MemberInfo[] members = typeof(CNBAStar).GetMembers();
- foreach (MemberInfo member in members)
- { ParseAttributes(member); }
-
- Console.ReadKey();
- }
-
-
- /** *************************************************************************************************
- * DESC : 将class的members所携带的信息一 一进行反射
- * ARGC :
- * @type: member's all infomation.
- * RET:
- *---------------------------------------------------------------------------------------------------
- ****************************************************************************************************/
- static void ParseAttributes(MemberInfo type)
- {
- object[] attributes = type.GetCustomAttributes(true);
- Console.WriteLine("{0} {1}'s attributes:", type.MemberType.ToString(), type.Name);
-
- if (attributes.Length != 0)
- {
- foreach (object attribute in attributes)
- {
- Console.WriteLine(" Attribute =[{0}]", attribute.ToString());
- DescriptionAttribute da = attribute as DescriptionAttribute;
- if (da != null)
- {
- Console.WriteLine(".Description = {0}",da.MData);
- if (da.ExtraInfo != "")
- Console.WriteLine(".ExtraInfo = {0}", da.ExtraInfo);
- else
- Console.WriteLine(".ExtraInfo=\"\"");
- }
- Console.WriteLine();
- }
- }
- else
- Console.WriteLine(" {0} has no attributes\n", type.Name);
- }
-
-
- [AttributeUsage(AttributeTargets.All)]
- public class DescriptionAttribute : Attribute
- {
- private string mData;
- private string mExtraInfo;
- private string mThirdInfo;
-
- public DescriptionAttribute(string data)
- {
- mData = data;
- mExtraInfo = "";
- mThirdInfo = "";
- }
-
- public string MData
- {
- get { return mData; }
- }
-
- /* Extra infomation */
- public string ExtraInfo
- {
- get { return mExtraInfo; }
- set { mExtraInfo = value; ; }
- }
-
- public string ThirdInfo
- {
- get { return mThirdInfo; }
- set { mThirdInfo = value; ; }
- }
- }
-
- }
- }
图2-1
上图是使用程序中使用了[Description]属性的类、方法、Property被反射出的属性信息。
三、定位参数与命令参数
自定义属性类中构造函数的参数称之为定位参数(即本例的data),任何公共读写字段或属性都是命令参数。两类参数的区别:
1、定位参数是构造函数带的参数,必须填写,下面是典型的报错:
- [Description]
- private string mName = "Michael Jordan";
错误 1 “CustomAttibute2.Program.DescriptionAttribute”不包含采用“0”参数的构造函数
2、命令参数能选择性填写,并且顺序不要求。
本例中的下面两种写法都是正确的
顺序一:
- [Description("I'm CNBAStar's mothed ShowTime()",ExtraInfo="public",ThirdInfo=="3#")]
- public string ShowTime()
顺序二:
- [Description("I'm CNBAStar's mothed ShowTime()",ThirdInfo=="3#",ExtraInfo="public")]
- public string ShowTime()
四、消除属性目标的歧义性
- [Description("I'm CNBAStar's mothed ShowTime()",ExtraInfo="public")]
- public string ShowTime()
- { return mName + " is most famous basketball player of the world!"; }
上面代码中,虽然.NET内部将这个Description习惯归于ShowTime()方法,但表面上看这样的写法仍然让人容易误解:这个属性到底是属性方法ShowTime()还是属性它的返回值?
为了解决这种歧义,在属性中添加了method和return参数作为区分,如下:
属性标识方法ShowTime2()
- [method: Description("I'm CNBAStar's mothed ShowTime2()")]
- public string ShowTime2()
- { return "Kobe Brynt is so so."; }
属性标识返回值
- [return: Description("Just mark the return value of showTime3() ")]
- public string ShowTime3()
- { return "Lebron James is so so."; }
参考文献:
1、http://edn.embarcadero.com/article/30250
Using Custom Attributes in C# - By David Clegg
2、http://msdn.microsoft.com/zh-cn/library/b3787ac0(v=vs.90).aspx
消除属性目标的歧义性
3、http://database.ctocio.com.cn/4/9344004.shtml
SQLServer:如何使用C#自定义属性
4、http://www.csharpwin.com/csharpspace/11732r3341.shtml