C# 特性

公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。 在.NET中,Attribute被用来处理多种问题,比如序列化、程序的安全特征、防止即时编译器对程序代码进行优化从而代码容易调试等等。

特性也是类,不同于其它类的是,特性必须继承子System.Attribute类,否则编译器分不清楚是普通类还是特性类。当编译器检测到是特性类时,他会识别出其中的信息存放在元数据中,仅此而已,编译器并不关心特性说了什么,特性也不会对编译器起到任何作用。

自定义特性有点类似于XML,它最大的好处不在于“它做了什么”,它真正最大的好处在于“你可以用它做什么”。这个是真正无止境的,由于自定义特性本身具有开放的特性,这使得它可以拥有更多新颖的用途。

这里假设某个类上使用了特性如下:
[XP]
class TEST{}
当编译器发现这个类TEST应用了XP特性时,首先会把字符串Attribute追加到这个名称后面,形成一个组合名称
XPAttribute,然后在其搜索路径的所有名称空间 (即using使用的命名空间)中搜索有指定名称的类,如果特性本身已Attribute结尾,编译器就不会再追加Attritude了,而是不修改该特性名。如下
[XPAttribute]
class TEST{}
编译器会找到含有该名称的类(XPAttribute),且这个类直接或者间接派生自System.Attribute。编译器还人为这个类包含控制特性用法的信息。
现在来看这个类的定义
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.ReturnValue | AttributeTargets.Assembly,AllowMultiple=true,Inherited=false)]
class XPAttribute:Attribute
{
public strin type;
public XPAttribute(string type) { this.type = type; }
}
指定AttributeUsage特性
特性(Attribute)本身用特性(System.AttributeUsage)来标记,C#编译器为它提供了特殊支持,其实AttributeUsage不能认为是一个特性了,应该理解为元特性,它只能用来标记特性类,不能标记其它的类。
使用:
AttributeUsage主要用于标识自定义特性可以应用到哪些类型的程序元素上。这些信息由它的第一个参数给出(AttributeTargets),像上面使用的一样。
特性应用于Assembly或者Module时,要这样写:
[assembly: someAssemblyAttribute(Parameters)]
[module: someAssemblyAttribute(Parameters)]
在指定自定义特性的有效目标元素时可以用为操作 |或运算符来组合 ,例如
该类有两个可选参数AllowMultiple和Inherited:
AllowMultiple 参数表示一个特性是否能够多次应用在同一项上。
Inherited 参数如果为true,表示应用到类或者接口上的特性也自动应用到所有派生类或者接口上。如果应用到方法或者属性上,就可以自动应用到该方法或属性等重写的版本上

反射使用
从类TEST中找XP特性
Type t = typeof(TEST);
从程序集中找XP特性
Assembly assembly = Assembly.Load(assembly);
Type[] types = assembly.GetTypes();

得到类上的自定义特性
object[] objs= t.GetCustomAttributes(typeof(XPAttribute),false);

得到方法上的自定义特性
object[] objs= t.GetMethod(“方法名”).GetCustomAttributes(typeof(XPAttribute),false);

你需要在GetCustomAttributes方法指定typeof(XPAttribute)参数,以限制仅仅返回你创建的自定义特性。第二参数false指定是否搜索该成员的继承链查找这些自定义特性。

遍历数组,将object转成TestAttribute特性才能访问其中的值
var xp = (XPAttribute)obj;
Debug.Log(xp.type);

例子:

using System;
using System.Reflection;
using UnityEngine;

[XP("TEST1Class")]
[XP("TEST1Class1")]
public class TEST1 : MonoBehaviour
{
    [XP("CanvasProperty")]
    public Canvas Canvas => null;
    [XP("CameraProperty")]
    public Camera ARCamera=>null;
    [XP("StartMethod")]
    public void Start()
    {
    
    }

    // Update is called once per frame
    [ContextMenu("测试")]
    void Test()
    {
        //得到当前执行的程序集
        var assembly = Assembly.GetExecutingAssembly();
        var types = assembly.GetTypes();
        foreach(var type in types)
        {
            //得到类上的特性
            var classXPAttributesObjs = type.GetCustomAttributes(typeof(XPAttribute), false);
            foreach (var classXPAttributesObj in classXPAttributesObjs)
            {
                var classXPAttribute = (XPAttribute)classXPAttributesObj;
                Debug.Log($"类{type.Name}上有XP特性,特性Type={classXPAttribute.Type}");
            }

            //得到属性上的特性
            var properties = type.GetProperties();
            foreach(var property in properties)
            {
                var propertyXPAttributeObjs = property.GetCustomAttributes(typeof(XPAttribute),false);
                foreach(var propertyXPAttributeObj in propertyXPAttributeObjs)
                {
                    var propertyXPAttribute = (XPAttribute)propertyXPAttributeObj;
                    Debug.Log($"类{type.Name}中的属性{property.Name}上有XP特性,特性值Type={propertyXPAttribute.Type}");
                }
            }

            //得到方法上的特性

            var methods = type.GetMethods( );
            foreach (var method in methods)
            {
                var methodXPAttributeObjs = method.GetCustomAttributes(typeof(XPAttribute), false);
                foreach (var methodXPAttributeObj in methodXPAttributeObjs)
                {
                    var methodXPAttribute = (XPAttribute)methodXPAttributeObj;
                    Debug.Log($"类{type.Name}方法{method.Name}上有XP特性,特性值Type={methodXPAttribute.Type}");
                }
            }
        }
        
    }
}
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class XPAttribute : Attribute
{
    public string Type;
    public XPAttribute(string type)
    {
        this.Type = type;
    }
}

输出结果
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值