以前我有寫過一篇有關,打標簽和反射的應用,主要用於類中字段的驗證。下面是連接 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.總結:
本博客描述的例子很牽強,不過只是感覺這種想法還是不錯的。方便項目的擴展。希望對大家有用。同時也是自己為了回顧一下反射和打標簽的用法,才打算寫這篇博客的。