1. 程式人生 > >C# 高階特性(二)Attribute和反射

C# 高階特性(二)Attribute和反射

使用Attribute的時候大多需要用到反射,所以放在一起。

Attribute:

我的理解是,它可以給你的類、方法、欄位等新增一些描述性語言,在執行期間又可以通過反射的方法獲取它的內容。

在編譯期間就初始化好了。

反射:

通過反射可以在不瞭解物件的內容時,操作物件。

優點:在執行的時候才需要獲取物件內容,提示程式的靈活性,降低耦合等。

缺點:操作效率低,會暴露私有的屬性和方法等。

舉例:

我有一個父類Animal,他有四個子類:Cat、Dog、Lion、Tiger。

    public class Animal
    { }
    public class Cat : Animal
    { }
    public class Dog : Animal
    { }
    public class Lion : Animal
    { }
    public class Tiger : Animal
    { }

假設我們需要寫一個方法,描述動物叫聲的大小,我們認為Cat和Dog的叫聲小,屬於一類,Lion和Tiger的叫聲大,屬於一類。

如果不用Attribute和反射機制,那麼我們需要給每個動物都定義叫聲這個方法。但是,如果用Attribute和反射機制用的話,則,我們可以把Cat和Dog定義一個方法,Lion和Tiger定義一個方法。

定義一個自定義attribute:

    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    public class CallBindingAttribute : Attribute
    {
        private Type m_CallType;
        public Type CallType
        {
            get { return m_CallType; }
        }
        internal CallBindingAttribute(Type callType)
        {
            m_CallType = callType;
        }
    }

定義動物叫聲:

    public class CallType
    {
        public enum Level
        {
            LOW = 1,
            HIGH = 2
        }


        private Level m_CallLevel;
        public Level CallLevel
        {
            get { return m_CallLevel; }
            internal set { m_CallLevel = value; }
        }
    }

定義大型動物和小動物叫聲,並繫結我們自定義的屬性:

    [CallBinding(typeof(Cat))]
    [CallBinding(typeof(Dog))]
    public class SmallAnimalType : CallType
    {
        public SmallAnimalType()
        {
            this.CallLevel = Level.LOW;
        }
    }


    [CallBinding(typeof(Lion))]
    [CallBinding(typeof(Tiger))]
    public class BigAnimalType : CallType
    {
        public BigAnimalType()
        {
            this.CallLevel = Level.HIGH;
        }
    }

通過反射獲取合適動物叫聲:

 public static List<CallType> Calls = new List<CallType>();
        public static List<CallType> GetFaultTypes(Type type)
        {
            List<CallType> cts = new List<CallType>();
            foreach (CallType ct in Calls)
            {
                object[] os = ct.GetType().GetCustomAttributes(typeof(CallBindingAttribute), false); // 反射方法,通過繫結的CallBindingAttribute和類獲取到合適的叫聲
                foreach (CallBindingAttribute dba in os)
                {
                    if (dba.CallType == type || type.IsSubclassOf(dba.CallType))
                    {
                        cts.Add(ct);
                        break;
                    }
                }
            }
            return cts;
        }

根據動物型別獲取到動物叫聲:

    SmallAnimalType sType = new SmallAnimalType(); // 載入動物叫聲
    Calls.Add(sType);
     BigAnimalType bType = new BigAnimalType();
    Calls.Add(bType);
    Dog dog = new Dog();
     List<CallType> DogCall = GetFaultTypes(dog.GetType()); // 根據動物型別Dog獲取狗的叫聲
     foreach (CallType callType in DogCall)
     {
             Console.WriteLine(callType.CallLevel.ToString());  //輸出為獅子的叫聲  HIGH
     }

     List<CallType> LionCall = GetFaultTypes(lion.GetType());
     foreach (CallType callType in LionCall)
     {
             Console.WriteLine(callType.CallLevel.ToString());//輸出為狗的叫聲  LOW
     }