最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#自定義Attribute值的獲取與優(yōu)化技巧

 更新時間:2023年07月05日 11:54:48   作者:junjieok  
C#自定義Attribute值的獲取是開發(fā)中會經(jīng)常用到的,大家通常使用反射進(jìn)行獲取的,代碼也很簡單,今天通過本文給大家講解C#?Attribute值獲取方法,感興趣的朋友跟隨小編一起看看吧

首先說下什么是Atrribute

首先,我們肯定Attribute是一個類,下面是msdn文檔對它的描述:

公共語言運(yùn)行時允許你添加類似關(guān)鍵字的描述聲明,叫做attributes,它對程序中的元素進(jìn)行標(biāo)注,如類型、字段、方法和屬性等。Attributes和Microsoft .NET Framework文件的元數(shù)據(jù)保存在一起,可以用來向運(yùn)行時描述你的代碼,或者在程序運(yùn)行的時候影響應(yīng)用程序的行為。

在.NET中,Attribute被用來處理多種問題,比如序列化、程序的安全特征、防止即時編譯器對程序代碼進(jìn)行優(yōu)化從而代碼容易調(diào)試等等。下面,我們先來看幾個在.NET中標(biāo)準(zhǔn)的屬性的使用,稍后我們再回過頭來討論Attribute這個類本身。(文中的代碼使用C#編寫,但同樣適用所有基于.NET的所有語言)

Attribute作為編譯器的指令

在C#中存在著一定數(shù)量的編譯器指令,如:#define DEBUG, #undefine DEBUG, #if等。這些指令專屬于C#,而且在數(shù)量上是固定的。而Attribute用作編譯器指令則不受數(shù)量限制。比如下面的三個Attribute:

   Conditional:起條件編譯的作用,只有滿足條件,才允許編譯器對它的代碼進(jìn)行編譯。一般在程序調(diào)試的時候使用。

   DllImport:用來標(biāo)記非.NET的函數(shù),表明該方法在一個外部的DLL中定義。

   Obsolete:這個屬性用來標(biāo)記當(dāng)前的方法已經(jīng)被廢棄,不再使用了。

C# Attribute值獲取

C#自定義Attribute值的獲取是開發(fā)中會經(jīng)常用到的,一般我們的做法也就是用反射進(jìn)行獲取的,代碼也不是很復(fù)雜。

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的類

[Description("Customer Information")]
[Name("customer_info")]
public class CustomerInfo
{
    [Name("name")]
    public string Name { get; set; }
    [Name("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上的值。有的同學(xué)可能就覺得這還不簡單呀,直接上代碼

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值了。雖然我們是獲取到了我們想要的,但是我們發(fā)現(xiàn)這樣做是不是太累了,如果又?jǐn)U展一個自定義的Attribute,或者又在一個新的屬性或字段上標(biāo)上Attribute時,我們又要寫一段代碼來實現(xiàn)我想要的,這些嚴(yán)重代碼違反了DRY的設(shè)計原則。我們知道獲取Attribute是通過反射來取的,Attribute那個值又是不變的,這樣就沒必要每次都要進(jìn)行反射來獲取了?;谝陨蟽牲c代碼進(jìn)行了如下的優(yōu)化,優(yōu)化后的代碼如下:

using System;
using System.Collections.Concurrent;
using System.Reflection;
public static class CustomAttributeExtensions
{
    /// <summary>
    /// Cache Data
    /// </summary>
    private static readonly ConcurrentDictionary<string, object> Cache = new ConcurrentDictionary<string, object>();
    /// <summary>
    /// 獲取CustomAttribute Value
    /// </summary>
    /// <typeparam name="TAttribute">Attribute的子類型</typeparam>
    /// <typeparam name="TReturn">TReturn的子類型</typeparam>
    /// <param name="sourceType">頭部標(biāo)有CustomAttribute類的類型</param>
    /// <param name="attributeValueAction">取Attribute具體哪個屬性值的匿名函數(shù)</param>
    /// <returns>返回Attribute的值,沒有則返回null</returns>
    public static TReturn GetCustomAttributeValue<TAttribute, TReturn>(this Type sourceType, Func<TAttribute, TReturn> attributeValueAction)
        where TAttribute : Attribute
    {
        return _getAttributeValue(sourceType, attributeValueAction, null);
    }
    /// <summary>
    /// 獲取CustomAttribute Value
    /// </summary>
    /// <typeparam name="TAttribute">Attribute的子類型</typeparam>
    /// <typeparam name="TReturn">TReturn的子類型</typeparam>
    /// <param name="sourceType">頭部標(biāo)有CustomAttribute類的類型</param>
    /// <param name="attributeValueAction">取Attribute具體哪個屬性值的匿名函數(shù)</param>
    /// <param name="propertyName">field name或property name</param>
    /// <returns>返回Attribute的值,沒有則返回null</returns>
    public static TReturn GetCustomAttributeValue<TAttribute, TReturn>(this Type sourceType, Func<TAttribute, TReturn> attributeValueAction, string propertyName)
        where TAttribute : Attribute
    {
        return _getAttributeValue(sourceType, attributeValueAction, propertyName);
    }
    #region private methods
    private static TReturn _getAttributeValue<TAttribute, TReturn>(Type sourceType, Func<TAttribute, TReturn> attributeFunc, string propertyName)
        where TAttribute : Attribute
    {
        var cacheKey = BuildKey<TAttribute>(sourceType, propertyName);
        var value = Cache.GetOrAdd(cacheKey, k => GetValue(sourceType, attributeFunc, propertyName));
        if (value is TReturn) return (TReturn)Cache[cacheKey];
        return default(TReturn);
    }
    private static string BuildKey<TAttribute>(Type type, string propertyName) where TAttribute : Attribute
    {
        var attributeName = typeof(TAttribute).FullName;
        if (string.IsNullOrEmpty(propertyName))
        {
            return type.FullName + "." + attributeName;
        }
        return type.FullName + "." + propertyName + "." + attributeName;
    }
    private static TReturn GetValue<TAttribute, TReturn>(this Type type, Func<TAttribute, TReturn> attributeValueAction, string name)
        where TAttribute : Attribute
    {
        TAttribute attribute = default(TAttribute);
        if (string.IsNullOrEmpty(name))
        {
            attribute = type.GetCustomAttribute<TAttribute>(false);
        }
        else
        {
            var propertyInfo = type.GetProperty(name);
            if (propertyInfo != null)
            {
                attribute = propertyInfo.GetCustomAttribute<TAttribute>(false);
            }
            else
            {
                var fieldInfo = type.GetField(name);
                if (fieldInfo != null)
                {
                    attribute = fieldInfo.GetCustomAttribute<TAttribute>(false);
                }
            }
        }
        return attribute == null ? default(TReturn) : attributeValueAction(attribute);
    }
    #endregion
}

優(yōu)化后的代碼:

把不同的代碼用泛型T,Fun<TAttribute,TReturn>來處理來減少重復(fù)的代碼;
把取過的Attribute值存到一個ConcurrentDictionary中,下次再來取時,如果有則直接取ConcurrentDictionary中的值,如果沒有才通過反射來取相應(yīng)的Attribute值,這樣大大的提高效率;  

調(diào)用方法也更加的簡單了,代碼如下:

var customerInfoName = typeof(CustomerInfo).GetCustomAttributeValue<NameAttribute, string>(x => x.Name);
var customerAddressName = typeof(CustomerInfo).GetCustomAttributeValue<NameAttribute, string>(x => x.Name, "Address");
var customerInfoDesc = typeof(CustomerInfo).GetCustomAttributeValue<DescriptionAttribute, string>(x => x.Description);
Console.WriteLine("CustomerInfo Name:" + customerInfoName);
Console.WriteLine("customerInfo >Address Name:" + customerAddressName);
Console.WriteLine("customerInfo Desc:" + customerInfoDesc);

運(yùn)行結(jié)果:

到此這篇關(guān)于C#自定義Attribute值的獲取與優(yōu)化的文章就介紹到這了,更多相關(guān)C# Attribute值獲取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C#如何加密解密RAR文件

    詳解C#如何加密解密RAR文件

    這篇文章主要為大家詳細(xì)介紹了C#如何實現(xiàn)加密解密RAR文件的功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • C#實現(xiàn)對數(shù)組進(jìn)行隨機(jī)排序類實例

    C#實現(xiàn)對數(shù)組進(jìn)行隨機(jī)排序類實例

    這篇文章主要介紹了C#實現(xiàn)對數(shù)組進(jìn)行隨機(jī)排序類,實例分析了C#數(shù)組與隨機(jī)數(shù)操作技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • 事務(wù)在c#中的使用

    事務(wù)在c#中的使用

    這篇文章介紹了事務(wù)在c#中的使用,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • C#窗體通訊錄系統(tǒng)的示例代碼

    C#窗體通訊錄系統(tǒng)的示例代碼

    本文主要介紹了C#窗體通訊錄系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • C#使用Data?Annotations進(jìn)行手動數(shù)據(jù)驗證

    C#使用Data?Annotations進(jìn)行手動數(shù)據(jù)驗證

    這篇文章介紹了C#使用Data?Annotations進(jìn)行手動數(shù)據(jù)驗證的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C#用遞歸算法解決經(jīng)典背包問題

    C#用遞歸算法解決經(jīng)典背包問題

    背包問題有好多版本,本文只研究0/1版本,即對一個物體要么選用,要么就拋棄,不能將一個物體再繼續(xù)細(xì)分的情況。
    2016-06-06
  • WPF自動隱藏的消息框的實例代碼

    WPF自動隱藏的消息框的實例代碼

    本文給大家介紹WPF自動隱藏的消息框?qū)嵗a,當(dāng)鼠標(biāo)放上去將一直顯示,移開動畫繼續(xù),提供normal和error兩種邊框。非常不錯,具有參考借鑒價值,感興趣的朋友一起看下吧
    2016-07-07
  • C#控制臺模擬電梯工作原理

    C#控制臺模擬電梯工作原理

    簡單的模擬一下電梯的運(yùn)行,電梯內(nèi)部和外部樓層呼叫的優(yōu)先級判斷。以前學(xué)硬件的時候做這個不成問題,現(xiàn)在用軟件來模擬對我來說比較難,要C#的圖形界面。求高手賜教。
    2015-06-06
  • C# 創(chuàng)建Excel氣泡圖的實例代碼

    C# 創(chuàng)建Excel氣泡圖的實例代碼

    這篇文章主要介紹了C# 創(chuàng)建Excel氣泡圖的實例代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • C#自定義緩存封裝類實例

    C#自定義緩存封裝類實例

    這篇文章主要介紹了C#自定義緩存封裝類,涉及C#針對緩存的寫入、讀取及設(shè)置過期時間等常用操作,并封裝進(jìn)一個類中便于調(diào)用,非常具有實用價值,需要的朋友可以參考下
    2015-03-03

最新評論

三原县| 昭平县| 保靖县| 西乌| 确山县| 犍为县| 宁安市| 内乡县| 隆回县| 小金县| 浦县| 纳雍县| 临夏县| 澄城县| 香格里拉县| 拜泉县| 庄河市| 德化县| 崇义县| 沈丘县| 梁山县| 汶上县| 宝清县| 子洲县| 安塞县| 岑巩县| 封开县| 石台县| 眉山市| 莱阳市| 卓资县| 易门县| 沅陵县| 克东县| 丁青县| 凤冈县| 鄂托克前旗| 万荣县| 双桥区| 如东县| 乐至县|