cjavapy编程之程

C# 特性标签(Attribute)

C# 中,特性(Attribute) 是一种用于向程序的元素(类、方法、属性等)添加元数据的机制。特性提供了一种强大的方式,可以在运行时或编译时对程序行为进行标注、控制或扩展。特性标签是 C# 中一种强大的元数据机制,可以向代码元素添加额外的声明性信息。这些信息可以被编译器、运行时环境和自定义代码使用,从而实现各种功能,如代码标记、序列化控制、条件编译和自定义元数据管理。

1、特性(Attribute)

 使用特性,可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。 将特性与程序实体相关联后,可以在运行时使用 反射 这项技术查询特性。

特性具有以下属性:

1)特性向程序添加元数据。 元数据 是程序中定义的类型的相关信息。 所有 .NET 程序集都包含一组指定的元数据,用于描述程序集中定义的类型和类型成员。 可以添加自定义特性来指定所需的其他任何信息。

2)可以将一个或多个特性应用于整个程序集、模块或较小的程序元素(如类和属性)。

3)特性可以像方法和属性一样接受自变量。

4)程序可使用反射来检查自己的元数据或其他程序中的元数据。

使用特性(Attribute):

可以将特性附加到几乎任何声明中,尽管特定特性可能会限制可有效附加到的声明的类型。 在 C# 中,通过用方括号 ([]) 将特性名称括起来,并置于应用该特性的实体的声明上方以指定特性。

例如,

[Serializable]
public class SampleClass
{
      private string code = "csharp";
      private string name = "cjavapy";
      private int age = 0; 
}

2、常用特性标签(Attribute)

1)控件开发常用Attribute

BrowsableAttribute :描述是否一个属性或事件应该被显示在属性浏览器里。

CategoryAttribute :描述一个属性或事件的类别,当使用类别的时候,属性浏览器按类别将属性分组。

DescriptionAttribute :当用户在属性浏览器里选择属性的时候,description里指定的文本会显示在属性浏览器的下边,向用户显示属性的功能。

BindableAttribute :描述是否一个属性倾向于被绑定。

DefaultPropertyAttribute :为组件指定一个默认的属性,当用户在Form设计器上选择一个控件的时候,默认属性会在属性浏览器里被选中。   

DefaultValueAttribute :为一个简单类型的属性设置一个默认值。

EditorAttribute :为属性指定一个特殊的编辑器。

LocalizableAttribute :指示一个属性是否能被本地化,任何有这个Attribute的属性将会被持久化到资源文件里。 

DesignerSerializationVisibilityAttribute:指示一个属性是否或者如何持久化到代码里。

指示一个属性是否串行化和如何串行化,它的值是一个枚举,一共有三种类型Content,Hidden,Visible。Content指示代码生成器为对象包 含 的内容生成代码,而不是为对象本身,Hidden指示代码生成器不为对象生成代码,visible指示代码生成器为对象生成代码。假如你的控件 有一 个集合属性,又想在设计时自动将集合属性的内容生成代码,那么就使用这个Attribute,并将值设为DesignerSerializationVisibility.Content。

TypeConverterAttribute :为属性指定一个类型转换器,类型转换器能将属性的值转化成其它的数据类型。

DefaultEventAttribute :为组件指定一个默认的事件,当用户在form设计其中选择一个控件的时候,在属性浏览器中这个事件被选中。

2) Web services常用Attribute

WebMethodAttribute:向使用 ASP.NET 创建的 XML Web service 中的某个方法添加此特性后,就可以从远程 Web 客户端调用该方法。 此类不能被继承。

WebServiceAttribute:用于向 XML Web services 添加附加信息,如描述其功能的字符串。

WebServiceBindingAttribute:声明用于定义一个或多个 XML Web service 方法的绑定。 此类不能被继承。

3)调用非托管代码Attribute

DllImportAttribute:指示由非托管动态链接库 (DLL) 公开为静态入口点的特性化方法。

4)类和方法常用Attribute

ObsoleteAttribute:标记不再使用的程序元素。 此类不能被继承。一般标记不推荐使用的方法或类。

ParamArrayAttribute:指示方法在其调用中将允许数目可变的自变量。 此类不能被继承。

SerializableAttribute:表示类可以序列化。 此类不能被继承。

5)Xml操作常用Attribute

XmlElementAttribute:指示公共字段或属性在 XmlSerializer 序列化或反序列化包含它们的对象时表示 XML 元素。

XmlIgnoreAttribute:指示 Serialize(TextWriter, Object) 的 XmlSerializer 方法不序列化公共字段或公共读/写属性值。

XmlIncludeAttribute:允许 XmlSerializer 在它序列化或反序列化对象时识别类型。

XmlNamespaceDeclarationsAttribute:指定目标属性、参数、返回值或类成员包含与 XML 文档中使用的命名空间相关联的前缀。

XmlRootAttribute:控制视为 XML 根元素的属性目标的 XML 序列化。

XmlTextAttribute:当串行化或反序列化包含该成员的类时,向 XmlSerializer 指示应将该成员作为 XML 文本处理。

XmlTypeAttribute:控制当属性目标由 XmlSerializer 序列化时生成的 XML 架构。

3、创建自定义特性

可通过定义特性类创建自己的自定义特性,特性类是直接或间接派生自 Attribute 的类,可快速轻松地识别元数据中的特性定义。 假设希望使用编写类型的程序员的姓名来标记该类型。 可能需要定义一个自定义 Author 特性类:

例如,

[System.AttributeUsage(System.AttributeTargets.Class |  
                       System.AttributeTargets.Struct)  
]  
public class AuthorAttribute : System.Attribute  
{  
    private string name;  
    public double version;  
    public AuthorAttribute(string name)  
    {  
        this.name = name;  
        version = 1.0;  
    }  
}  

注意:类名 AuthorAttribute 是该特性的名称,即 Author 加上 Attribute 后缀。 由于该类派生自 System.Attribute,因此它是一个自定义特性类。

1)第一个参数 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。可以使用|指定多个。

2)参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。

3)inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。

使用Attribute方法如下:

[Author("cjavapy", version = 1.0)]  
class SampleClass  
{  
      private string code = "csharp";
      private string name = "cjavapy";
      private int age = 0;
}  

AttributeUsage 有一个命名参数 AllowMultiple,通过此命名参数可一次或多次使用自定义特性。

例如,

[System.AttributeUsage(System.AttributeTargets.Class |  
                       System.AttributeTargets.Struct,  
                       AllowMultiple = true)  
]                      // 可以使用多个Attribute
public class AuthorAttribute : System.Attribute  

使用时一个可以指定多个标签,

例如,

[Author("cjavapy", version = 1.1)]  
[Author("levi", version = 1.2)]
class SampleClass
{
private string code = "csharp";
private string name = "cjavapy";
private int age = 0;
}

4、运行时读取特性(反射)

可以使用反射(Reflection)在运行时读取一个类、方法、属性等上面定义的特性(Attribute)。

1)定义一个自定义特性 Attribute

[AttributeUsage(AttributeTargets.Class 
| AttributeTargets.Method 
| AttributeTargets.Property)]
public class MyInfoAttribute : Attribute
{
    public string Description { get; }
    public int Version { get; }

    public MyInfoAttribute(string description, int version)
    {
        Description = description;
        Version = version;
    }
}

2)应用这个特性到类或方法上

[MyInfo("这个一个类", 1)]
public class MyClass
{
    [MyInfo("这是一个简单的方法", 2)]
    public void MyMethod()
    {
        Console.WriteLine("Method executed.");
    }
}

3)使用反射读取这个特性

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // 获取类的类型
        Type type = typeof(MyClass);

        // 获取类上的特性
        var classAttribute = (MyInfoAttribute)Attribute
        .GetCustomAttribute(type, typeof(MyInfoAttribute));
        if (classAttribute != null)
        {
            Console.WriteLine("Class Attribute: "+
            $"Description = {classAttribute.Description},"
            +$"Version = {classAttribute.Version}");
        }

        // 获取方法上的特性
        MethodInfo method = type.GetMethod("MyMethod");
        var methodAttribute = (MyInfoAttribute)Attribute
        .GetCustomAttribute(method, 
        typeof(MyInfoAttribute));
        if (methodAttribute != null)
        {
            Console.WriteLine("Method Attribute:"+ 
            $"Description = {methodAttribute.Description}"+
            $",Version = {methodAttribute.Version}");
        }
    }
}
推荐阅读
cjavapy编程之路首页