.NET 特性随笔
.net中有特性和属性,很多时候初学者会认为属性和特性是一回事儿,实际上,特性是.NET框架中一门技术,通俗的说,我们可以把特性理解成为一个特殊的类,他继承Attribute 来对代码进行特殊的约束。
自定义的特性就是我们自己定义的一个类,其继承了Attrubute,如:
我们对表的字段MODEL做一个简单的特性约定类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /// <summary> 2 /// 数据表列名映射 3 /// </summary> 4 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 5 public sealed class ColumnMap : Attribute 6 { 7 public ColumnMap() 8 { 9 //构造 10 } 11 /// <summary> 12 /// 映射字段 13 /// </summary> 14 /// <param name="_ColumnName">列字段名</param> 15 /// <param name="_ColumnLen">长度</param> 16 /// <param name="_DataType">数据类型</param> 17 /// <param name="_Remark">字段说明</param> 18 /// <param name="_IsNull">是否允许空值</param> 19 /// <param name="_PrimaryKey">是否为主键</param> 20 /// <param name="_Mark">是否为自增或默认值,True:则不对此列进行Insert与Update操作</param> 21 public ColumnMap(string _ColumnName, string _ColumnLen, object _DataType, string _Remark, bool _IsNull, bool _PrimaryKey, bool _Mark) 22 { 23 this.ColumnName = _ColumnName; 24 this.ColumnLen = _ColumnLen; 25 this.DataType = _DataType; 26 this.Remark = _Remark; 27 this.IsNull = _IsNull; 28 this.PrimaryKey = _PrimaryKey; 29 this.Mark = _Mark; 30 } 31 /// <summary> 32 /// 列字段名 33 /// </summary> 34 public string ColumnName { get; set; } 35 /// <summary> 36 /// 长度 37 /// </summary> 38 public string ColumnLen { get; set; } 39 /// <summary> 40 /// 数据类型 41 /// </summary> 42 public object DataType { get; set; } 43 /// <summary> 44 /// 字段说明 45 /// </summary> 46 public string Remark { get; set; } 47 /// <summary> 48 /// 是否允许空值 49 /// </summary> 50 public bool IsNull { get; set; } 51 /// <summary> 52 /// 是否为主键 53 /// </summary> 54 public bool PrimaryKey { get; set; } 55 /// <summary> 56 /// 是否为自增或默认值,True则不对此列进行INSERT和UPDATE 57 /// </summary> 58 public bool Mark { get; set; } 59 }
接下来使用这个特性来约定MODEL中的属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /// <summary> 2 /// 权限菜单,TablMap请自行定义 3 /// </summary> 4 [Serializable] 5 [TableMap("Affair_Parames", "Role_Menu")] 6 public class Role_Menu 7 { 8 /// <summary> 9 /// 编号 10 /// </summary> 11 [ColumnMap("Menu_Id", null, DbType.Int32, "自动编号", false, true, true)] 12 public int? Menu_Id { get; set; } 13 14 /// <summary> 15 /// 功能名称 16 /// </summary> 17 [ColumnMap("Menu_Name", "50", DbType.String, "功能名称", false, false, false)] 18 public string Menu_Name { get; set; } 19 20 /// <summary> 21 /// 功能层级深度 22 /// </summary> 23 [ColumnMap("Menu_Depth", null, DbType.Int32, "功能层级深度", false, false, false)] 24 public int Menu_Depth { get; set; } 25 26 /// <summary> 27 /// 父级功能 28 /// </summary> 29 [ColumnMap("Menu_Parent", null, DbType.Int32, "父级功能", false, false, false)] 30 public int Menu_Parent { get; set; } 31 32 /// <summary> 33 /// 功能状态 34 /// </summary> 35 [ColumnMap("Menu_state", null, DbType.Int32, "功能状态", false, false, false)] 36 public int Menu_state { get; set; } 37 38 /// <summary> 39 /// 功能类型 40 /// </summary> 41 [ColumnMap("Menu_Type", null, DbType.Int32, "功能类型", false, false, false)] 42 public int Menu_Type { get; set; } 43 44 /// <summary> 45 /// 功能说明 46 /// </summary> 47 [ColumnMap("Menu_Remarks", "500", DbType.String, "功能说明", false, false, false)] 48 public string Menu_Remarks { get; set; } 49 50 /// <summary> 51 /// 功能指向 52 /// </summary> 53 [ColumnMap("Menu_Link", "500", DbType.String, "功能指向", false, false, false)] 54 public string Menu_Link { get; set; } 55 56 /// <summary> 57 /// 功能所在层级排序 58 /// </summary> 59 [ColumnMap("Menu_Index", null, DbType.Int32, "功能所在层级排序", false, false, false)] 60 public int Menu_Index { get; set; } 61 62 /// <summary> 63 /// 功能事件参数 64 /// </summary> 65 [ColumnMap("Menu_Task", "150", DbType.String, "功能事件参数", false, false, false)] 66 public string Menu_Task { get; set; } 67 }
现在已经使用ColumnMap对Role_Menu类中的属性是行约束。
那么这个特性的约束有什么用?
在没有后继调用的情况下,这个约束什么用也没用,只起到个说明功能!接下来,就调用这个特性。那么,如何来调用这个特性呢?反射!
首先我们先定义一个类及其方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /// <summary> 2 /// 获取指定属性对象的特性 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public sealed class AttributeProperty<T> where T : class 6 { 7 public static T GetTableMapAttribute(PropertyInfo t) 8 { 9 T Map = default(T); 10 T[] MapAttributes = t.GetCustomAttributes(typeof(T), true) as T[]; 11 if (MapAttributes.Length > 0) 12 { 13 Map = MapAttributes[0]; 14 } 15 return Map; 16 } 17 18 }
接下来就调用这个类,来获取前面所做的MODEL的特性
Role_Menu Menu = new Role_Menu(); PropertyInfo[] Pinfos= Menu.GetType().GetProperties(); //也可以
/*
PropertyInfo[] Pinfos= typeof(Role_Menu).GetProperties();
*/
/*
MethodInfo[]....针对方法
*/
foreach (PropertyInfo P in Pinfos) {
ColumnMap Map = AttributeProperty<ColumnMap>.GetTableMapAttribute(P);
if (Map != null)
{
//这里你想做什么就做什么,ColumnMap在指定给Role_Menu类时的特性参数值就都在这里了***原数据***********
}
}
如果想获取某个类的特性,可以采用下面这个方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /// <summary> 2 /// 获取指定类对象的特性 3 /// </summary> 4 public sealed class AttributeTag<T, A> 5 where T : class 6 where A : class 7 { 8 /// <summary> 9 /// 获取表所映射的特性 10 /// </summary> 11 /// <param name="t">对象</param> 12 /// <returns></returns> 13 public static A GetTableMapAttribute(T t) 14 { 15 A Map = default(A); 16 Type MapType = t.GetType(); 17 A[] MapAttributes = MapType.GetCustomAttributes(typeof(A), true) as A[]; 18 if (MapAttributes.Length > 0) 19 { 20 Map = MapAttributes[0]; 21 } 22 return Map; 23 } 24 }
其中A:特性类,T:使用特性的类
小结:
特性就是一个类,继承Attribute,可以应用于类,方法,属性等
要获取特性的内容,则需要通地反射的方式来得到。