自定义属性的作用
有时候我们需要给一个类或者类中的成员加上一些属性或者附加信息,让类或者变量的功能更明确可控制的细粒度更高,打个简单的比方:数据库里面的一张表,表中的每一个字段都有很多属性,如是否主键,默认值,注释信息等等,我们在编写实体类的时候,如何表示这些信息呢?通过自定义属性可以实现。
自定义属性的实现步骤
我说了不算,权威说了算:
- 声明一个类,并将 AttributeUsageAttribute 属性应用到该类中。类的名称即为新属性的名称
- 声明该类从 System.Attribute 继承:
- 定义 Private 字段来存储属性值:
- 需要时,请为属性创建构造函数:
- 为属性 (Attribute) 定义方法、字段和属性 (Property):
实例一个:
属性类(和相关枚举)
///
<summary>
/// 数据库字段的用途。
/// </summary>
public enum EnumDBFieldUsage
{
/// <summary>
/// 未定义。
/// </summary>
None = 0x00 ,
/// <summary>
/// 用于主键。
/// </summary>
PrimaryKey = 0x01 ,
/// <summary>
/// 用于唯一键。
/// </summary>
UniqueKey = 0x02 ,
/// <summary>
/// 由系统控制该字段的值。
/// </summary>
BySystem = 0x04
}
[AttributeUsage(AttributeTargets.Property, Inherited = true )]
public class DBFieldAttribute:Attribute
{
EnumDBFieldUsage m_usage;
string m_strFieldName;
string m_strDescription;
object m_defaultValue;
public DBFieldAttribute( string strFieldName, object defaultValue,EnumDBFieldUsage usage, string strDescription)
{
m_strFieldName = strFieldName;
m_defaultValue = defaultValue;
m_usage = usage;
m_strDescription = strDescription;
}
public DBFieldAttribute( string fieldName) : this (fieldName, null , EnumDBFieldUsage.None, null )
{ }
public DBFieldAttribute( string fieldName, EnumDBFieldUsage usage) : this (fieldName, null ,usage, null )
{ }
// 获取该成员映射的数据库字段名称。
public string FieldName
{
get
{
return m_strFieldName;
}
set
{
m_strFieldName = value;
}
}
// 获取该字段的默认值
public object DefaultValue
{
get
{
return m_defaultValue;
}
set
{
m_defaultValue = value;
}
}
}
/// 数据库字段的用途。
/// </summary>
public enum EnumDBFieldUsage
{
/// <summary>
/// 未定义。
/// </summary>
None = 0x00 ,
/// <summary>
/// 用于主键。
/// </summary>
PrimaryKey = 0x01 ,
/// <summary>
/// 用于唯一键。
/// </summary>
UniqueKey = 0x02 ,
/// <summary>
/// 由系统控制该字段的值。
/// </summary>
BySystem = 0x04
}
[AttributeUsage(AttributeTargets.Property, Inherited = true )]
public class DBFieldAttribute:Attribute
{
EnumDBFieldUsage m_usage;
string m_strFieldName;
string m_strDescription;
object m_defaultValue;
public DBFieldAttribute( string strFieldName, object defaultValue,EnumDBFieldUsage usage, string strDescription)
{
m_strFieldName = strFieldName;
m_defaultValue = defaultValue;
m_usage = usage;
m_strDescription = strDescription;
}
public DBFieldAttribute( string fieldName) : this (fieldName, null , EnumDBFieldUsage.None, null )
{ }
public DBFieldAttribute( string fieldName, EnumDBFieldUsage usage) : this (fieldName, null ,usage, null )
{ }
// 获取该成员映射的数据库字段名称。
public string FieldName
{
get
{
return m_strFieldName;
}
set
{
m_strFieldName = value;
}
}
// 获取该字段的默认值
public object DefaultValue
{
get
{
return m_defaultValue;
}
set
{
m_defaultValue = value;
}
}
}
此代码说明了如何制作自定义属性类。其实跟一般的类的区别就是此类继承自Attribute,加上AttributeUsage是属性上的属性,是可选的。
数据访问层实体类:
class
DalObj
{
string m_strTableName;
int m_nID;
string m_strName;
string m_password;
public DalObj( string strTableName)
{
m_strTableName = strTableName;
}
[DBField( " id " ,EnumDBFieldUsage.PrimaryKey)]
public int ID
{
get { return m_nID; }
set { m_nID = value; }
}
[DBField( " name " ,DefaultValue = " 游客 " )]
public string Name
{
get { return m_strName; }
set { m_strName = value; }
}
[DBField( " pwd " )]
public string PassWord
{
get { return m_password; }
set { m_password = value; }
}
}
{
string m_strTableName;
int m_nID;
string m_strName;
string m_password;
public DalObj( string strTableName)
{
m_strTableName = strTableName;
}
[DBField( " id " ,EnumDBFieldUsage.PrimaryKey)]
public int ID
{
get { return m_nID; }
set { m_nID = value; }
}
[DBField( " name " ,DefaultValue = " 游客 " )]
public string Name
{
get { return m_strName; }
set { m_strName = value; }
}
[DBField( " pwd " )]
public string PassWord
{
get { return m_password; }
set { m_password = value; }
}
}
此代码说明了如何使用自定义的属性。有两点需要注意的地方
第一:类名可以跟自定义的类名一样,也可以加上或减去后面的Attribute,本例子中就是使用的时候跟自定义的类名减少了“Attribute”。
第二:属性参数填写方法,如果自定义属性类(例子中DBFieldAttribute)自己的构造函数带参数,那么这些参数是必选的,可以重载构造函数以满足不同组合,必选参数填完之后,可以继续给自定义属性类中的公共成员带命名地赋值,如例子中的 DefaultValue="游客" 一句就是命名参数。
遍历自定义属性的代码:
DalObj dalObj
=
new
DalObj(
"
users
"
);
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo proInfo in dalObj.GetType().GetProperties())
{
object [] attrs = proInfo.GetCustomAttributes( typeof (DBFieldAttribute), true );
if (attrs.Length == 1 )
{
DBFieldAttribute attr = (DBFieldAttribute)attrs[ 0 ];
sb.Append(attr.FieldName + " : " + (attr.DefaultValue == null ? " null " : attr.DefaultValue.ToString()) + " \r\n " );
}
}
MessageBox.Show(sb.ToString());
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo proInfo in dalObj.GetType().GetProperties())
{
object [] attrs = proInfo.GetCustomAttributes( typeof (DBFieldAttribute), true );
if (attrs.Length == 1 )
{
DBFieldAttribute attr = (DBFieldAttribute)attrs[ 0 ];
sb.Append(attr.FieldName + " : " + (attr.DefaultValue == null ? " null " : attr.DefaultValue.ToString()) + " \r\n " );
}
}
MessageBox.Show(sb.ToString());
此代码说明了如何检索自定义属性的值,主要用到了GetCustomAttributes来获取属性值。