特性:是一個類,可以用來標記元素,編譯時生成到metadata裏,平時不影響程序的運行,除非主動用反射去查找,可以得到一些額外的信息/操作,然後給提供了更豐富擴展空間 。特性可以在不破壞類型封裝的前提下,額外的增加功能 例如AOP:面向切面編程 。特性是一個直接/間接繼承自Attribute的類,約定俗成用attribute結尾,然後聲明的時候可以省略
按照 《特性是一個直接/間接繼承自Attribute的類,約定俗成用attribute結尾,然後聲明的時候可以省略》的說法,我們先自定義一個特性
using System;
namespace MyAttribute
{
/// <summary>
/// AttributeTargets.All(說明這個特性可以標記在什麼元素上,類、字段、屬性、方法、返回值等元素,ALL代表所有)
/// AllowMultiple(說明這個特性在同一個元素上使用的次數,默認一個元素只能標記一種特性,但可以多種特性並存)
/// Inherited(說明這個特性是否可以繼承)
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class CustomAttribute : Attribute
{
public CustomAttribute()
{
Console.WriteLine("這裏是CustomAttribute");
}
public CustomAttribute(string remark)
{
Console.WriteLine("這裏是CustomAttribute帶參數");
}
public string Remark { get; set; }
public string Description { get; set; }
public void Show()
{
Console.WriteLine($"This is {this.GetType().Name}");
}
}
public class CustomChildAttribut : CustomAttribute
{
}
public class AuthorityAttribute : Attribute
{
public string Remark { get; set; }
public bool IsLogin()
{
return new Random().Next(100, 200) > new Random().Next(99, 199);
}
}
}
這樣我們一個自定義的特性就建立好了,然後我們怎麼使用的呢?看下面的事例
先創建一個student類然後我們可以這麼添加
using MyAttribute.Extend;
using System;
namespace MyAttribute
{
/// <summary>
/// 這裏是註釋,除了讓人看懂這裏寫的是什麼,
/// 對運行沒有任何影響
///
/// 特性可以影響編譯器
/// 特性可以影響程序運行
/// 特性其實是生成metadata的
/// </summary>
//[CustomAttribute]
//[Custom]
//[Custom()]
//[Custom("這裏是學生")]
//[Custom("這裏是學生", Description = "123456")]
//[Custom("這裏是學生", Remark = "123456")]
//[Custom(Description = "123456", Remark = "123456")]
[Custom("這裏是學生", Description = "123456", Remark = "123456")]
//[Obsolete("請不要使用這個了,請使用什麼來代替", true)]//標記過期
//[Serializable]//可以序列化和反序列化
public class Student
{
[Custom]
public Student()
{
Console.WriteLine("這裏是student");
}
[Custom]
public int Id { get; set; }
[RequirdValidate]
public string Name { get; set; }
[LongValidateAttribute(1000, 99999999999)]
public long QQ { get; set; }
[Custom]
public string Remark;
[Custom]
public void Study()
{
//new Thread(null).Suspend()
Console.WriteLine($"這裏是{this.Name}跟着Eleven老師學習");
}
[AuthorityAttribute(Remark = "回答問題")]
[Custom]
[return: Custom]
public string Answer([Custom]string name)
{
return $"This is {name}";
}
}
}
這樣我們自定義的特性和特性可以使用的地方就都清楚了,但是我們怎麼讓這個特殊的類(特性)發揮用處呢?那就要看下面的事例
在剛剛的student類中我們在很多元素上標記了特性,下面我要讓這些特性發揮作用
PeopleManager全部code,包括對類、屬性、字段、構造函數、方法、方法參數、方法返回值的特性檢測
using MyAttribute.Extend;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace MyAttribute
{
/// <summary>
/// 特性 編譯後是 metadata 只有反射才能使用
/// 包了一層 專門來使用特性
/// </summary>
public class PeopleManager
{
public static void Manage(Student student)
{
{
//有了特性 可以多一點行爲 權限檢查 可以多一點信息
//Type type = typeof(Student);
Type type = student.GetType();
MethodInfo method = type.GetMethod("Answer");
if (method.IsDefined(typeof(AuthorityAttribute), true))
{
object item = method.GetCustomAttributes(typeof(AuthorityAttribute), true)[0];
AuthorityAttribute attribute = item as AuthorityAttribute;
UnityEngine.Debug.Log(attribute.Remark);
if (!attribute.IsLogin())
{
throw new Exception("沒有權限");//redirect
}
}
student.Answer("菜鳥海瀾");
}
#region
{
Type type = student.GetType();
if (type.IsDefined(typeof(CustomAttribute), true))//檢測這個類是否含有指定的特性
{
object item = type.GetCustomAttributes(typeof(CustomAttribute), true)[0];
{
CustomAttribute attribute = item as CustomAttribute;
attribute.Show();
}
}
foreach (var item in type.GetProperties())//檢測屬性是否含有指定的特性
{
if (item.IsDefined(typeof(CustomAttribute), true))
{
object oAttribute = item.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
}
foreach (var item in type.GetFields())//檢測字段是否含有指定的特性
{
if (item.IsDefined(typeof(CustomAttribute), true))
{
object oAttribute = item.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
}
foreach (var item in type.GetConstructors())//檢測構造函數是否含有指定的特性
{
if (item.IsDefined(typeof(CustomAttribute), true))
{
object oAttribute = item.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
}
MethodInfo method = type.GetMethod("Answer");
if (method.IsDefined(typeof(CustomAttribute), true))//檢測對應的方法是否含有指定的特性
{
object oAttribute = method.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
foreach (var item in method.GetParameters())//檢測對應函數的參數是否含有指定的特性
{
if (item.IsDefined(typeof(CustomAttribute), true))
{
object oAttribute = item.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
}
if (method.ReturnParameter.IsDefined(typeof(CustomAttribute), true))//檢測對應函數的返回值是否含有指定的特性
{
object oAttribute = method.ReturnParameter.GetCustomAttributes(typeof(CustomAttribute), true)[0];
CustomAttribute attribute = oAttribute as CustomAttribute;
// Do Something....
}
}
#endregion
}
}
}
特性擴展
完成code
using System;
namespace MyAttribute.Extend
{
public abstract class AbstractValidateAttribute : Attribute
{
public abstract bool Validate(object oValue);
}
public class LongValidateAttribute : AbstractValidateAttribute
{
private long _lMin = 0;
private long _lMax = 0;
public LongValidateAttribute(long lMin, long lMax)
{
this._lMin = lMin;
this._lMax = lMax;
}
public override bool Validate(object oValue)
{
return this._lMin < (long)oValue && (long)oValue < this._lMax;
}
}
public class RequirdValidateAttribute : AbstractValidateAttribute
{
public override bool Validate(object oValue)
{
return oValue != null;
}
}
public class DataValidate
{
public static bool Validate<T>(T t)
{
Type type = t.GetType();
bool result = true;
foreach (var prop in type.GetProperties())
{
if (prop.IsDefined(typeof(AbstractValidateAttribute), true))
{
object item = prop.GetCustomAttributes(typeof(AbstractValidateAttribute), true)[0];
AbstractValidateAttribute attribute = item as AbstractValidateAttribute;
if (!attribute.Validate(prop.GetValue(t)))
{
result = false;
break;
}
}
}
return result;
}
}
}
using System;
using System.Reflection;
namespace MyAttribute.Extend
{
/// <summary>
/// 是給枚舉用 提供一個額外信息
/// </summary>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
public class RemarkAttribute : Attribute
{
public RemarkAttribute(string remark)
{
this.Remark = remark;
}
public string Remark { get; private set; }
}
public static class RemarkExtend
{
/// <summary>
/// 擴展方法
/// </summary>
/// <param name="enumValue"></param>
/// <returns></returns>
public static string GetRemark(this Enum enumValue)
{
Type type = enumValue.GetType();
FieldInfo field = type.GetField(enumValue.ToString());
if (field.IsDefined(typeof(RemarkAttribute), true))
{
RemarkAttribute remarkAttribute = (RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute));
return remarkAttribute.Remark;
}
else
{
return enumValue.ToString();
}
}
}
[Remark("用戶狀態")]
public enum UserState
{
/// <summary>
/// 正常
/// </summary>
[Remark("正常")]
Normal = 0,
/// <summary>
/// 凍結
/// </summary>
[Remark("凍結")]
Frozen = 1,
/// <summary>
/// 刪除
/// </summary>
[Remark("刪除")]
Deleted = 2
}
}
作者:su9257_海瀾
鏈接:https://www.jianshu.com/p/39f1acf789ac