這篇文章主要介紹“C#的屬性Attribute的作用”,在日常操作中,相信很多人在C#的屬性Attribute的作用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”C#的屬性Attribute的作用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
柯城網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)成立于2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
屬性Attributes在C#中很常用,但事實(shí)上很多人對(duì)這個(gè)東西又很陌生。
從概念上講,屬性提供的是將元數(shù)據(jù)關(guān)系到元素的一種方式。
屬性使用的樣子,應(yīng)該都見(jiàn)過(guò):
[Flags] //Attribute public enum DayOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, Wednesday = 8, Thursday = 16, Friday = 32, Saturday = 64 }
代碼中,F(xiàn)lags就是一個(gè)屬性。
通常,屬性會(huì)放在類(lèi)、字段、方法等定義的上面,用來(lái)指定特定的內(nèi)容。
.Net Framework框架提供了一些屬性。像常見(jiàn)的Serializable,用來(lái)告訴編譯器當(dāng)前的類(lèi)可以序列化成JSON或XML:
[Serializable] public class SerializableClass { /*...*/ }
需要注意的是,屬性在編譯時(shí)會(huì)嵌入到程序集中。這樣,我們可以使用反射來(lái)獲得相應(yīng)的屬性值。
二、自定義屬性
自定義屬性用處很大,算是我自己比較常用的一個(gè)技術(shù)。
自定義屬性需要從System.Attribute抽象類(lèi)來(lái)繼承。
想象一個(gè)場(chǎng)景。我們?cè)跇?gòu)建一個(gè)手機(jī)類(lèi)。我們需要一個(gè)屬性來(lái)表示手機(jī)一些信息,比方口牌和生產(chǎn)年份:
public class MobileInformationAttribute : Attribute { public string brand { get; set; } public int yearOfProduct { get; set; } public MobileInformationAttribute(string Brand, int YearOfProduct) { brand = Brand; yearOfProduct = YearOfProduct; } }
我們會(huì)注意到:屬性是一個(gè)類(lèi),和其它類(lèi)一樣,擁有字段、方法、構(gòu)造函數(shù)和其它成員。
三、使用屬性
前面說(shuō)了,屬性可以放在類(lèi)、字段、方法等定義的上面。
我們來(lái)看看上面這個(gè)自定義屬性的使用:
[MobileInformation("Apple", 2021)] public class IPhone12 { /*...*/ }
這兒需要注意一下:對(duì)于自定義屬性的名字,如果我們采用xxx+Attribute的名稱(chēng),則使用時(shí)我們可以用短名稱(chēng)xxx。否則,就需要使用完整的名稱(chēng):
public class abc : Attribute { /*...*/ } [abc("Apple", 2021)] public class IPhone12 { /*...*/ }
四、限制屬性
屬性本身也是一個(gè)類(lèi)。所以屬性也可以用屬性來(lái)指定和修飾。
在修飾屬性的屬性中,有一個(gè)框架中的屬性用的很多,就是AttributeUsage。這個(gè)屬性用來(lái)限制自定義屬性可以修飾的元素類(lèi)型:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class MobileInformationAttribute : Attribute { /*...*/ }
AttributeTargets是一個(gè)枚舉,有很多選項(xiàng),包括類(lèi)、接口、方法、構(gòu)造函數(shù)、枚舉、程序集等。
上邊的代碼,我們限定了屬性只用于指定和修飾類(lèi)和接口。所以,如果用這個(gè)屬性來(lái)修飾一個(gè)字段,編譯器會(huì)報(bào)錯(cuò)。
AttributeUsage還允許我們定義從修飾對(duì)象繼承的對(duì)象,是否也獲得屬性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = true)] public class MobileInformationAttribute : Attribute { /*...*/ }
以及該屬性是否可以在一個(gè)元素上有多個(gè)實(shí)例:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public class MobileInformationAttribute : Attribute { /*...*/ }
五、訪問(wèn)屬性
有了屬性,怎么訪問(wèn)呢?
框架提供了一個(gè)方法Attribute.GetCustomAttribute():
var mobileType = typeof(IPhone12); var attributeType = typeof(MobileInformationAttribute); var attribute = (MobileInformationAttribute)Attribute.GetCustomAttribute(mobileType, attributeType); Console.WriteLine($"Mobile is {attribute.brand} {attribute.yearOfProduct}");
六、反射訪問(wèn)
反射最主要的作用,是用來(lái)收集對(duì)象的數(shù)據(jù),而不是對(duì)象本身的數(shù)據(jù)。這些數(shù)據(jù)包括對(duì)象的類(lèi)型,以及關(guān)于對(duì)象成員(包括方法、屬性、構(gòu)造函數(shù))的信息,和關(guān)于特定程序集的信息。此外,還包括存儲(chǔ)在元素屬性中的任何信息。
最簡(jiǎn)單的反射,就是GetType()方法。
int myInt = 5; Type type = myInt.GetType(); Console.WriteLine(type);
除此之外,我們還可以使用反射來(lái)獲取關(guān)于包含給定類(lèi)型的程序集的信息:
Assembly assembly = typeof(DateTime).Assembly; Console.WriteLine(assembly); Assembly mobileAssembly = typeof(IPhone12).Assembly; Console.WriteLine(mobileAssembly);
關(guān)于反射的內(nèi)容,不展開(kāi)討論。
這兒說(shuō)的,是通過(guò)反射獲取類(lèi)中方法的信息:
public class ReflectedClass { public string Property1 { get; set; } public int Add(int first, int second) { return first + second; } } ReflectedClass reflected = new ReflectedClass(); MemberInfo member = reflected.GetType().GetMethod("Add"); Console.WriteLine(member); //Int32 Add(Int32, Int32)
同樣,還可能通過(guò)反射獲得關(guān)于已定義的屬性的信息,以及關(guān)于對(duì)象的構(gòu)造函數(shù)的信息:
PropertyInfo property = reflected.GetType().GetProperty("Property1"); Console.WriteLine(property); //System.String Property1 ConstructorInfo constructor = reflected.GetType().GetConstructor(new Type[0]); Console.WriteLine(constructor); //Void .ctor()
七、使用反射創(chuàng)建實(shí)例
這個(gè)需要用到system.Activator。這是一個(gè)非常強(qiáng)大的類(lèi),可以從類(lèi)型創(chuàng)建對(duì)象的實(shí)例。
來(lái)看看這個(gè)方法的使用:
ReflectedClass newReflected = new ReflectedClass(); var reflectedType = newReflected.GetType(); object newObject = Activator.CreateInstance(reflectedType); Console.WriteLine(newObject);
八、使用反射處理泛型
使用反射處理泛型會(huì)比處理普通類(lèi)型麻煩一點(diǎn)。
這里需要知道,Type類(lèi)上有一個(gè)屬性用來(lái)標(biāo)識(shí)類(lèi)型是不是泛型:
Listnumbers = new List { 1, 2, 3, 4, 5, 6, 7 }; Console.WriteLine(numbers.GetType().IsGenericType);
同樣,我們也可以用反射來(lái)創(chuàng)建一個(gè)泛型的實(shí)例:
Listnumbers = new List { 1, 2, 3, 4, 5, 6, 7 }; Type d = numbers.GetType().GetGenericTypeDefinition(); Type[] typeArgs = new Type[] { typeof(int) }; Type constructed = d.MakeGenericType(typeArgs); object list = Activator.CreateInstance(constructed); Console.WriteLine(list.GetType());
有一點(diǎn)復(fù)雜,但可以實(shí)現(xiàn)。
到此,關(guān)于“C#的屬性Attribute的作用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!