他...我們絕非從未謀面
他...總是悄悄的守候在我們身旁
他...默默犧牲奉獻幫我們做了許多事
他是我們 最熟悉的陌生人
~ C# Attribute ~
此屬性 (Attribute) 非彼屬性 (Property)
對岸管他叫 "特性"
這裡還是叫他 Attribute 吧
M$ 的說明:
C# 提供了一個定義宣告式標記 (Tag) 的機制,此宣告標記稱為屬性 (Attribute),可以讓您在原始程式碼中放置一些實體,來指定額外的資訊。屬性所包含的資訊可以在 Run Time 時透過反映來擷取。您可以使用預先定義屬性 (Attribute)或者您可以定義自己的自訂屬性 http://msdn.microsoft.com/zh-tw/library/aa288059(v=vs.71).aspx
我們無時無刻都能瞥見 Attribute 的身影
加上 Attribute 我們的程式就被賦予了超能力
但是...Why?
為什麼明明我們什麼都沒做 只是加上 Attribute 程式就會多出一些能力呢?
答案顯而易見 自然是冥冥之中有股神秘的力量 Framework 幫我們完成了這些事
在 C# 物件導向 裡面通常都是靠 [繼承] 承接或擴充功能
但是[繼承]是一種垂直鏈狀的概念
當[繼承]深度越深的時候[可維護性]相對的就會變低(因為太多層了)
所以有句口訣叫做 多用合成 少用繼承
設法把不同功能拆分成 單一職責(Single Responsibility Principle)的小類別
再合體成模組級別的大類別 (怎麼合體自然也有一堆花招 EX:DI、IOC etc)
但是這僅止於 設計類別時內部自嗨的層面
有的時候需求來自是外部的
例如有個[顧客]類別有其自身的屬性方法
另外還有[店家]類別
[店家]類別自然無權干涉[顧客]類別的內部行為
理所當然[店家]對[顧客]提供服務
即便[店家]對外宣稱:我們無分男女、宗教、種族、階級、黨派,在服務上一律平等
但是用膝蓋骨想就知道那肯定是ㄊㄇ唬爛的
所以[店家]類別需要針對不同的[顧客]提供不同等級的服務
或許有人覺得那就給[顧客]一個叫做[顧客等級]的 Property 就能解決了
事實上的確可行 但是卻不是很合理
因為 Property 是屬於類別內部擁有的資訊 由類別決定如何提供給外界使用
如果[顧客]可以任意決定自身的[顧客等級]那未免也太可笑
這個時候應該使用 Attribute
Attribute 主要是給外部使用的資訊 LIKE 設定 貼標籤 註解 表述
以便[店家](外部)在使用[顧客](貼 Attribute 的類別)的時候能夠達成[提供不同等級的服務]的需求
講了那麼多 我想還是沒人懂 Attribute 到底在玩什麼把戲 (因為這就是 Attribute 的魅力特色呀 <3)
馬上來玩玩就對了
首先有兩個頁面 External 跟 Internal
分別使用 ExternalBulletin 跟 InternalBulletin
共用的部分繼承抽象類 Bulletin
Bulletin 在建構子 會使用 ArticlesFactory 來產生文章
Articles POPO 類 單純 DTO
如今響應個資法 需要 Articles 裡面的人名都改成 OO
這是一個外部因素帶來的改變 實際上 Articles 的本質不應該被改變 只是呈現的時候 人名必須要變成 OO
所以這裡設計一個 SilencerAttribute
裡面有個 SilencerMode 用來決定模式
現在可以給 ExternalBulletin 或 InternalBulletin 掛上 Attribute 了
基本上要掛哪個都可以(水平特性)
只是情境上是 外部的 Bulletin 需要保密
而內部的 Bulletin 則需要看到原始 Articles
只是掛上 Attribute 會怎樣嗎? 會有什麼事發生嗎??
用肋骨想就知道 當然不會怎麼樣 什麼鬼事也不會發生(鬼月的話就不敢保證)
Attribute 只是掛好看的標籤 自然是需要冥冥之的股神秘力量額外的類別來看這些 Attribute 做對應的變化 才會有效果
聰明的看官想必也早知道謎底了 就是 ArticlesFactory 要來幹這件事(因為[工廠]就是要[黑箱]作業呀)
這裡就能看到 ArticlesFactory 透過神奇的演算法(?) 巧妙的過濾人名 改成OO
結果顯而易見 就是 Articles 被改成OO 沒啥好講的
現在就能明白什麼是[水平擴充]了
水平層面上的 [類別] 或 [方法] 都能任意的掛上 Attribute 來擴充功能
抽換 Attribute 都不會影響該 [類別] 或 [方法] 內部的運作
但是對於 外部(會來看這些 Attribute 的 [類別] 或 [方法])來說 又能 [提供不同等級的服務]
這貨很神呀 根本可以 單排上金 的感覺 沒有缺點嗎?
缺點自然是有的
使用 Attribute 難以偵錯 因為你可能不知道 到底是誰在使用這些 Attribute
像是這個範例 是由 ArticlesFactory 來使用 Attribute 做判斷
如果並不清楚 ArticlesFactory 會使用 Attribute 的情況下
得到的 Articles 就會不如預期
可能就無法得知 到底為什麼 人名變成 OO 了
明明 CODE (垂直) 裡面都沒有寫到這段功能
這個情況在 分別開發的時候 會更顯著
那什麼時候適合使用 Attribute 呢?
.NET MVC 就是很好的示範了
Authorize HttpPost AllowHtml OutputCache
這些不影響 Controller 內部邏輯的功能 就能抽出來變成 Attribute 交由第三方 (Framework) 完成實作
最後 Attribute 還有個屌炸天的應用
極度推薦!
感謝你XD 我太晚知道能這樣用了~
回覆刪除:)
刪除寫得不錯 謝謝分享
回覆刪除:)
刪除坑,都是坑
回覆刪除好棒的解說,請問大大方便提供這段解說的Demo Code嗎?
回覆刪除網誌管理員已經移除這則留言。
回覆刪除這屌炸天的應用真是太重要了
回覆刪除