当前位置: 首页 > 科技观察

一篇文章讲解C#的Attribute

时间:2023-03-20 11:42:58 科技观察

一、AttributesAttributes在C#中很常用,但其实很多人对这个东西很陌生。从概念上讲,属性提供了一种将元数据与元素相关联的方法。你应该看过属性的使用方式:[Flags]//AttributepublicenumDayOfWeek{Sunday=1,Monday=2,Tuesday=4,Wednesday=8,Thursday=16,Friday=32,Saturday=64}在代码中,Flags是一个属性。通常,属性放在类、字段、方法等的定义之上,用来指定具体的内容。.NetFramework框架提供了一些属性。和常见的Serializable一样,用来告诉编译器当前类可以序列化成JSON或者XML:编译。这样我们就可以通过反射来获取对应的属性值了。2.自定义属性自定义属性非常有用,也是我用的比较多的一个技巧。自定义属性需要继承自System.Attribute抽象类。想象一个场景。我们正在构建一个手机类。我们需要一个属性来表示手机的一些信息,比如品牌、生产年份等:品牌;yearOfProduct=YearOfProduct;}}我们会注意到:属性是一个类,就像任何其他类一样,具有字段、方法、构造函数和其他成员。3、使用属性前面提到,属性可以放在类、字段、方法等的定义之上。我们来看看上面自定义属性的使用:[MobileInformation("Apple",2021)]publicclassIPhone12{/*...*/}这里需要注意的是:对于自定义属性的名称,如果我们使用xxx+Attribute名称时,我们可以使用简称xxx。否则需要使用全名:publicclassabc:Attribute{/*...*/}[abc("Apple",2021)]publicclassIPhone12{/*...*/}4.限制属性Attribute本身也是一类。所以属性也可以用属性来指定和修饰。在修改属性的属性中,有一个属性在框架中用的比较多,就是AttributeUsage。该属性用于限制自定义属性可以修改的元素类型:[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]publicclassMobileInformationAttribute:Attribute{/*...*/}AttributeTargets是一个有很多选项的枚举,包括类、接口、方法、构造函数、枚举、程序集等。在上面的代码中,我们将属性限制为只能指定和修改类和接口。因此,如果使用该属性修改字段,编译器会报错。AttributeUsage还允许我们定义从修改对象继承的对象是否也获得属性:[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface,Inherited=true)]publicclassMobileInformationAttribute:Attribute{/*...*/}以及是否属性可以在一个元素上有多个实例:[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface,AllowMultiple=false)]publicclassMobileInformationAttribute:Attribute{/*...*/}5.访问属性有了属性,如何访问?Framework提供了一个方法Attribute.GetCustomAttribute():varmobileType=typeof(IPhone12);varattributeType=typeof(MobileInformationAttribute);varattribute=(MobileInformationAttribute)Attribute.GetCustomAttribute(mobileType,attributeType);Console.WriteLine($"Mobileis{attribute.brand}{attribute.yearOfProduct}");6、反射访问反射的主要作用是收集对象的数据,而不是对象本身的数据。此数据包括对象的类型、有关对象成员的信息(包括方法、属性、构造函数)以及有关特定程序集的信息。还包括存储在元素属性中的任何信息。最简单的反射是GetType()方法。intmyInt=5;Typetype=myInt.GetType();Console.WriteLine(类型);此外,我们可以使用反射来获取有关包含给定类型的程序集的信息:Assemblyassembly=typeof(DateTime).Assembly;Console.WriteLine(assembly);AssemblymobileAssembly=typeof(IPhone12).Assembly;Console.WriteLine(mobileAssembly);反思的内容不再赘述。这里说的是通过反射获取类中方法的信息:publicclassReflectedClass{publicstringProperty1{get;set;}publicintAdd(intfirst,intsecond){returnfirst+second;}}ReflectedClassreflected=newReflectedClass();MemberInfmember=reflected。获取类型()。GetMethod("Add");Console.WriteLine(member);//Int32Add(Int32,Int32)同样,也可以通过反射获取定义的属性信息和对象构造函数的信息:PropertyInfoproperty=reflected。GetType().GetProperty("Property1");Console.WriteLine(property);//System.StringProperty1ConstructorInfoconstructor=reflected.GetType().GetConstructor(newType[0]);Console.WriteLine(constructor);//Void.ctor()七、使用反射创建实例这需要使用system.Activator。这是一个非常强大的类,可以从类型创建对象实例。我们来看看这个方法的使用:ReflectedClassnewReflected=newReflectedClass();varreflectedType=newReflected.GetType();objectnewObject=Activator.CreateInstance(reflectedType);Console.WriteLine(newObject);8.使用反射处理泛型使用反射处理泛型会比处理普通类型麻烦一点。这里需要知道在Type类上有一个属性来标识类型是否是泛型:Listnumbers=newList{1,2,3,4,5,6,7};Console。WriteLine(数字.GetType().IsGenericType);同样,我们也可以使用反射创建泛型实例:Listnumbers=newList{1,2,3,4,5,6,7};Typed=numbers.GetType().GetGenericTypeDefinition();Type[]typeArgs=newType[]{typeof(int)};Typeconstructed=d.MakeGenericType(typeArgs);objectlist=Activator.CreateInstance(constructed);Console.WriteLine(list.GetType());有点复杂,但可行。九、总结好像有点乱。总而言之,属性将元数据分配给元素,包括类、字段、方法等。此元数据在项目构建时编译,并描述元素,而不是元素的数据。您可以创建从Attribute类继承的自定义属性。AttributeUsage属性可以用来限制这些属性的使用位置,可以使用反射来获取属性数据。反射是一种允许获取有关元素(但不是元素本身)的元数据和信息的技术。执行反射最基本的方法是使用GetType()方法,但是反射也可以用来获取方法、构造函数、字段等信息。你可以使用反射来创建一个对象的实例,只要你有对象的类型。同时,也可以使用反射创建一个泛型对象,但是比较复杂,需要泛型对象的类型和所有泛型参数的类型。