1. 程式人生 > >C# 中自定義Attribute值的獲取與優化

C# 中自定義Attribute值的獲取與優化

C#自定義Attribute值的獲取是開發中會經常用到的,一般我們的做法也就是用反射進行獲取的,程式碼也不是很複雜。

1、首先有如下自定義的Attribute

[AttributeUsage(AttributeTargets.All)]
    public sealed class NameAttribute : Attribute
    {
        private readonly string _name;

        public string Name
        {
            get { return _name; }
        }

        public NameAttribute(string name)
        {
            _name = name;
        }
    }
2、定義一個使用NameAttribute的類
[Name("dept")]
    public class CustomAttributes
    {
        [Name("Deptment Name")]
        public string Name { get; set; }
        [Name("Deptment Address")]
        public string Address;
    }

3、獲取CustomAttributes類上的"dept"也就很簡單了
private static string GetName()
        {
            var type = typeof(CustomAttributes);
            var attribute = type.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault();
            if (attribute == null)
            {
                return null;
            }
            return ((NameAttribute)attribute).Name;
        }
以上程式碼就可以簡單的獲取,類上的Attribute的值了,但是需求往往不是這麼簡單的,不僅要獲取類頭部Attribute上的值,還要獲取欄位Address頭部Attribute上的值。有的同學可能就覺得這還不簡單呀,直接上程式碼
private static string GetAddress()
        {
            var type = typeof (CustomAttributes);
            var fieldInfo = type.GetField("Address");
            if (fieldInfo == null)
            {
                return null;
            }
            var attribute = fieldInfo.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault();
            if (attribute == null)
            {
                return null;
            }
            return ((NameAttribute) attribute).Name;
        }
上面程式碼就是獲取Address欄位頭部上的Attribute值了。雖然我們是獲取到了我們想要的,但是我們發現這樣做是不是太累了,如果又擴充套件一個自定義的Attribute,或者又在一個新的屬性或欄位上標上Attribute時,我們又要寫一段程式碼來實現我想要的,這些嚴重程式碼違反了DRY的設計原則。我們知道獲取Attribute是通過反射來取的,Attribute那個值又是不變的,這樣就沒必要每次都要進行反射來獲取了。基於以上兩點程式碼進行了如下的優化,優化後的程式碼如下:
public static class CustomAttributeHelper
    { 
        /// <summary>
        /// Cache Data
        /// </summary>
        private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>();

        /// <summary>
        /// 獲取CustomAttribute Value
        /// </summary>
        /// <typeparam name="T">Attribute的子型別</typeparam>
        /// <param name="sourceType">頭部標有CustomAttribute類的型別</param>
        /// <param name="attributeValueAction">取Attribute具體哪個屬性值的匿名函式</param>
        /// <returns>返回Attribute的值,沒有則返回null</returns>
        public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction) where T : Attribute
        {
            return GetAttributeValue(sourceType, attributeValueAction, null);
        }

        /// <summary>
        /// 獲取CustomAttribute Value
        /// </summary>
        /// <typeparam name="T">Attribute的子型別</typeparam>
        /// <param name="sourceType">頭部標有CustomAttribute類的型別</param>
        /// <param name="attributeValueAction">取Attribute具體哪個屬性值的匿名函式</param>
        /// <param name="name">field name或property name</param>
        /// <returns>返回Attribute的值,沒有則返回null</returns>
        public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction,
            string name) where T : Attribute
        {
            return GetAttributeValue(sourceType, attributeValueAction, name);
        }

        private static string GetAttributeValue<T>(Type sourceType, Func<T, string> attributeValueAction,
            string name) where T : Attribute
        {
            var key = BuildKey(sourceType, name);
            if (!Cache.ContainsKey(key))
            {
                CacheAttributeValue(sourceType, attributeValueAction, name);
            }

            return Cache[key];
        }

        /// <summary>
        /// 快取Attribute Value
        /// </summary>
        private static void CacheAttributeValue<T>(Type type,
            Func<T, string> attributeValueAction, string name)
        {
            var key = BuildKey(type, name);

            var value = GetValue(type, attributeValueAction, name);

            lock (key + "_attributeValueLockKey")
            {
                if (!Cache.ContainsKey(key))
                {
                    Cache[key] = value;
                }
            }
        }

        private static string GetValue<T>(Type type,
            Func<T, string> attributeValueAction, string name)
        {
            object attribute = null;
            if (string.IsNullOrEmpty(name))
            {
                attribute =
                    type.GetCustomAttributes(typeof (T), false).FirstOrDefault();
            }
            else
            {
                var propertyInfo = type.GetProperty(name);
                if (propertyInfo != null)
                {
                    attribute =
                        propertyInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault();
                }

                var fieldInfo = type.GetField(name);
                if (fieldInfo != null)
                {
                    attribute = fieldInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault();
                }
            }

            return attribute == null ? null : attributeValueAction((T) attribute);
        }

        /// <summary>
        /// 快取Collection Name Key
        /// </summary>
        private static string BuildKey(Type type, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return type.FullName;
            }

            return type.FullName + "." + name;
        }
    }
以上優化後的程式碼: 把不同的程式碼用泛型T,Fun<T,stirng>來處理來減少重複的程式碼; 把取過的Attribute值存到一個Dictionary中,下次再來取時,如果有則直接返回Dictionary中的值,如果沒有才通過反射來取相應的Attribute值,這樣大大的提高效率; 呼叫方法也更加的簡單了,程式碼如下
var cName=typeof(CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name);
var fName = typeof (CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name, "Address");
有沒有, 是不是很簡單,而且呼叫方式對快取是完全透明的!





相關推薦

C# 定義Attribute獲取優化

C#自定義Attribute值的獲取是開發中會經常用到的,一般我們的做法也就是用反射進行獲取的,程式碼也不是很複雜。 1、首先有如下自定義的Attribute [AttributeUsage(AttributeTargets.All)] public sealed

c#定義集合的實現

功能:集合,包含新增,刪除,計算交集,並集,補集,是否為子集 using System; using System.Collections; using System.Collections.Generic; public class CSet { private

C++定義型別列舉型別

不限定作用域列舉型別說明: 列舉元素是常量,不能對它們賦值 例如有如下定義enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT}; 不能寫賦值表示式:SU

C#定義控制元件隱藏基類成員(屬性、方法和事件)的方法

       編寫自定義控制元件時,總是繼承C#中提供的Control類,而Control類是C#中所有窗體控制元件的基類,裡面定義了大量的屬性、方法和事件,而很多基類成員在自定義控制元件中可能不需要,因為編寫者會希望在自定義控制元件中隱藏這些成員,避免使用者呼叫這些成員。

Unity3D定義

在用Unity3D開發跨平臺遊戲的時候很多時候需要對接各種不同裝置,這個時候就需要遊戲按鍵可以相容各種市場上的遙控器鍵值,雖然大部分遙控器鍵值相對統一,但是還是有個別遙控器鍵值相對個性一點,這個時候就需

C#定義屬性的例子

 自定義屬性的作用 有時候我們需要給一個類或者類中的成員加上一些屬性或者附加資訊,讓類或者變數的功能更明確可控制的細粒度更高,打個簡單的比方:資料庫裡面的一張表,表中的每一個欄位都有很多屬性,如是否主鍵,預設值,註釋資訊等等,我們在編寫實體類的時候,如何表示這些資訊呢?

C#定義高精度Timer定時器的實例教程

edm 想要 精確 方式 mes 監視 工具 討論 etime Timer 用於以用戶定義的事件間隔觸發事件。Windows 計時器是為單線程環境設計的,其中,UI 線程用於執行處理。它要求用戶代碼有一個可用的 UI 消息泵,而且總是在同一個線程中操作,或者將調用封送到另一

c# 定義屬性 有 {get; set} 和沒有{get; set} 的區別

取值 public 之前 {} 的區別 一個 自動屬性 至少 定義 屬性:public int age{get;set;}    //自動屬性    public int age{} 這種編譯不通過,get和set至少有一個,分別代表,取值和賦值 變量:public i

@Value取不到的原因(引用application.properties定義

@service 引用 ring nal 原因 sta fin 配置 app 在spring mvc架構中,如果希望在程序中直接使用properties中定義的配置值,通常使用一下方式來獲取: @Value("${tag}") private String tagV

JavaScript定義函數以及文本框、radio、下拉框的獲取,結合淘寶競拍案例來理解。。。

支付寶 價格 select back html alt 文本框 lec 獲取 淘寶競拍案例: HTML部分代碼: <form action="#" method="post"> <h2>歡迎進入淘寶競拍</h2> &l

VS2008定義C++工程模板修改新建檔案預設編碼的辦法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Struts定義標籤獲取棧valuestack

    首先,要糾正下在《自定義-擴充套件struts2的標籤》一文中筆者的分析。在該文中筆者說,     最近在做j2ee的專案,需要封裝很多標籤,發現直接從BodyTagSupport繼承的話,無法獲取valuestack,也無法借用struts的國際化解決方案。所以需

spring定義註解(annotation)AOP獲取註解

一、自定義註解(annotation) 自定義註解的作用:在反射中獲取註解,以取得註解修飾的類、方法或屬性的相關解釋。 package me.lichunlong.spring.annotation;

java定義註解並通過反射獲取註解屬性

直接上程式碼,註釋中有說明: 1、定義自定義註解類(類註解和欄位註解): package com.uno.ray;   import java.lang.annotation.Documented;   import java.lang

.net c#獲取定義Attribute

前言: 在c#開發中,有時候我們需要讀取 Attribute中的資訊(關於Attribute , 我自己把他理解成一個可以為類,屬性標記的東西,這個標記可以為你提供一些關於類,方法,屬性的額外資訊) 我們如何獲取這些標記的資訊,如何獲取自定義Attribute資訊。

spring定義註解(annotation)獲取註解

註解類自定義 package me.lichunlong.spring.annotation; import java.lang.annotation.Documented;    import j

js獲取html下拉框選中定義屬性

<select id="city" onchange="city_change(this)""> <option value="1" tag="010">北京</option> <option value="1" tag="02

轉:C#制作ORM映射學習筆記一 定義Attribute

技術 sage 其中 username pac ont 學習 collect reat 之前在做unity項目時發現只能用odbc連接數據庫,感覺非常的麻煩,因為之前做web開發的時候用慣了ORM映射,所以我想在unity中也用一下ORM(雖然我知道出於性能的考慮這樣做事不

C/C++const關鍵字的用法及其定義的比較

類型安全 屬性 const關鍵字 code oid 程序 函數返回值 存儲空間 臨時對象 1.const關鍵字的性質 簡單來說:const關鍵字修飾的變量具有常屬性。 即它所修飾的變量不能被修改。 2.修飾局部變量 1 const int a = 10; 2 int co

c#(winform)定義ListItem類方便ComboBox添加Item項

urn left over string his 定義 return box item 1.定義ListItem類 public class ListItem { private string _key = string.Empty;