標籤:
以前我有寫過一篇有關,打標籤和反射的應用,主要用於類中欄位的驗證。下面是串連 C#基礎---Attribute(標籤) 和 reflect(反射) 應用。 這個項目迭代發現公司項目裡面發現老代碼對業務擴充比較大的地方又通過打標籤和反射做了一個小的架構,感覺挺實用的。於是想一想模仿一下就搬到部落格園上。寫得可能不好,也請各位博友指點.
背景: 【為了方便,自己還是類比一個背景吧, 感覺不是很恰當,不過自己的Demo裡面自己這樣寫的.當然跟公司的比起來肯定不夠完善】
每個人都會吃飯,可是每個國家吃飯的習慣不一樣。中國人吃湯圓,加拿大人吃意大利麵,美國人吃火雞。還有其他國家的人吃其他東西。如何來維護不同國家的不同習俗呢。我開了一家飯店,目前有中國,美國,加拿大的食物,如果來了一個人,我們如何讓程式自動通過該人的國籍,來判斷他是要吃什麼呢。 這就要靠打標籤和反射來解決了。下面來看Demo吧.
1.實體類.
首先我們定義一個基類,Person基類裡面定義虛擬方法,每個人都會吃東西。
Person(Country=PersonCountry.UNKnown)] public class Person { public virtual void Eat() { Console.WriteLine("我們吃東西"); } }
再次,不同國家的人, 去繼承基類,重寫eat方法,體現不同國家的吃飯習慣.
[Person(Country=PersonCountry.USA)] public class USA : Person { public override void Eat() { Console.WriteLine("我們吃火雞"); } } [Person(Country=PersonCountry.China)] public class Chinese : Person { public override void Eat() { Console.WriteLine("我們吃湯圓"); } } [Person(Country=PersonCountry.USA)] public class USA : Person { public override void Eat() { Console.WriteLine("我們吃火雞"); } }
2.標籤
為了區分每一個類具體是哪個國家的人,我們設定了一個Person標籤,和PersonCountry枚舉
public class PersonAttribute:Attribute { private PersonCountry _country = PersonCountry.UNKnown; public PersonCountry Country { get { return _country; } set { this._country = value; } } } public enum PersonCountry { USA, China, Canada, UNKnown }
3. Helper方法:
實體類和枚舉已經定義好。 那如何讓程式自動區分,人的國籍,然後確認他們的吃飯習慣呢。下面可以通過反射來判斷.
A. Assembly.GetExecutingAssembly() 可以擷取當前的程式級,assembly.GetTypes() 擷取所有的類型,包括USA,Canda,Chinese 資訊
B. (PersonAttribute)Attribute.GetCustomAttribute(currentType, typeof(PersonAttribute));擷取當前類的標籤,然後用標籤與傳進來的countryType進行比較,確認Person類型.
C. 然後通過InvokeMember來建立對象,返回
public class PersonHelper { public static Person GetPersonObj(PersonCountry contryType) { Assembly assembly = Assembly.GetExecutingAssembly(); Type[] typeList = assembly.GetTypes(); foreach (Type currentType in typeList) { var attribute = (PersonAttribute)Attribute.GetCustomAttribute(currentType, typeof(PersonAttribute)); if (attribute!=null && attribute.Country == contryType) { return currentType.InvokeMember(null, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, new object[] { }) as Person; } } return new Person(); } }
4. 測試方法:
可能前面大家迷迷糊糊,下面來看看測試,可能會比較明白:
Note: 1. 如果新進來的人,是中國人,只需要調用Helper方法然後擷取到Chinese對象,然後執行對應的eat方法。
2. 如果本店想知道韓國人的吃飯習慣,只需要多增加一個類,然後打上對應的標籤就OK了。
public static void Main(string[] args) { Person p1 = PersonHelper.GetPersonObj(PersonCountry.China); p1.Eat(); //輸出:我們吃湯圓 Person p2 = PersonHelper.GetPersonObj(PersonCountry.Canada); p2.Eat(); //輸出:我們吃意大利麵 }
5.總結:
本部落格描述的例子很牽強,不過只是感覺這種想法還是不錯的。方便項目的擴充。希望對大家有用。同時也是自己為了回顧一下反射和打標籤的用法,才打算寫這篇部落格的。
C#基礎---Attribute(標籤) 和 reflect(反射) 應用二