Unity--特性(一)

特性:是一個類,可以用來標記元素,編譯時生成到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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章