首先来看一下微软官方对Attributes(C#)的定义:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/index

Attributes provide a powerful method of associating metadata, or declarative information, with code (assemblies, types, methods, properties, and so forth). After an attribute is associated with a program entity, the attribute can be queried at run time by using a technique called reflection. For more information, see Reflection (C#).

Attributes have the following properties:

  • Attributes add metadata to your program. Metadata is information about the types defined in a program. All .NET assemblies contain a specified set of metadata that describes the types and type members defined in the assembly. You can add custom attributes to specify any additional information that is required. For more information, see, Creating Custom Attributes (C#).

  • You can apply one or more attributes to entire assemblies, modules, or smaller program elements such as classes and properties.

  • Attributes can accept arguments in the same way as methods and properties.

  • Your program can examine its own metadata or the metadata in other programs by using reflection. For more information, see Accessing Attributes by Using Reflection (C#).

这段英文很简单,我们可以Get到如下几个点:

1,Attributes可以向你的程序中添加元数据。元数据是指你在程序中定义的类型的信息,所有的.net程序集都包含了一组描述定义类型以及类型成员的元数据。

2,可以添加一到多个Attribute到程序集,模块或者类。

3,Attributes可以接受参数。

4,程序可以利用反射来检查自己的元数据。

我们先抛开反射,看Attributes的定义,感觉Attributes像是在描述一个类:可以添加成员变量,可以写入元数据,可以接受参数。

而当我们使用的时候,需要这样写:

[DllImportAttribute("xxx,dll")]

或者这样

[DllImport("xxx.dll")]

注意,这里都没有分号。如果你还有特殊需求的话,可以写上可选参数,比如:

[DllImport("xxx.dll", ExactSpelling=false, SetLastError=false)]

我们可以看到这里语法有些怪异,首先是方括弧的使用,其次是函数参数的赋值上,如果我们需要写入赋值的参数名,往往会这么写:ExactSpelling : false。最后当我们使用Attributes的时候, 它附着的地方也很奇怪,看上去不像是类或者方法的一部门,但却能对类或者方法产生影响。

下面我们写一个系统自带的Attributes的范例:

假设我们有一个日志系统,分布在代码各处,主要分为3大类:网络日志(输出网络回调的各种状态),游戏内逻辑日志(用于调试信息),引擎底层日志(比如我们重写了UGUI)。日志的等级分为低等级,普通,紧急三种状态。

我们使用同一个日志管理系统来输出对应的日志。现在我希望能够过滤固定类型的日志,并且每次更改过滤条件的时候尽可能少地改动代码。这个案例在这里可能并不恰当,过滤日志的话还有很多更好更快的代码,这里仅做参考。

    public class ToolKit
{
/// <summary>
/// 网络日志
/// </summary>
[Conditional("Network")]
[Conditional("Low")]
public static void LogNetworkLow()
{
Console.WriteLine("LogNetworkLow");
} [Conditional("Network")]
[Conditional("Normal")]
public static void LogNetworkNormal()
{
Console.WriteLine("LogNetworkNormal");
} [Conditional("Network")]
[Conditional("Urgent")]
public static void LogNetworkUrgent()
{
Console.WriteLine("LogNetworkUrgent");
} /// <summary>
/// 逻辑日志
/// </summary>
[Conditional("Logic")]
[Conditional("Low")]
public static void LogLogicLow()
{
Console.WriteLine("LogLogicLow");
} [Conditional("Logic")]
[Conditional("Normal")]
public static void LogLogicNormal()
{
Console.WriteLine("LogLogicNormal");
} [Conditional("Logic")]
[Conditional("Urgent")]
public static void LogLogicUrgent()
{
Console.WriteLine("LogLogicUrgent");
} /// <summary>
/// 引擎日志
/// </summary>
[Conditional("Engine")]
[Conditional("Low")]
public static void LogEngineLow()
{
Console.WriteLine("LogEngineLow");
} [Conditional("Engine")]
[Conditional("Normal")]
public static void LogEngineNormal()
{
Console.WriteLine("LogEngineNormal");
} [Conditional("Engine")]
[Conditional("Urgent")]
public static void LogEngineUrgent()
{
Console.WriteLine("LogEngineUrgent");
}
}

首先我们定义了一个ToolKit的类,里面有诺干静态函数,每个静态函数负责输出特定的日志(请无视这垃圾代码)。在每个函数上面,我们加了类似条件的东西。Conditional是系统定义的一个Attribute,作用是过滤条件。这段代码很好看懂,只是语法让人觉得有点诡异。

接着我们在主程序中,把所有输出都打印一遍。

static void Main(string[] args)
{
ToolKit.LogNetworkLow();
ToolKit.LogNetworkNormal();
ToolKit.LogNetworkUrgent(); ToolKit.LogLogicLow();
ToolKit.LogLogicNormal();
ToolKit.LogLogicUrgent(); ToolKit.LogEngineLow();
ToolKit.LogEngineNormal();
ToolKit.LogEngineUrgent(); Console.ReadKey();
}

执行程序,然而什么输出也没有。这说明我们设置的条件生效了。接下来我们在CS文件头上加入#define Normal。

似乎和我们的预期相同。把#define Normal改为#define Logic,再次运行。

完美。现在我想输出低等级的网络日志,在原来的#define Logic下面再加入一行#define Low,然后运行。

Oops,条件筛选似乎用了或而没用与。这里是一个需要注意的点,如果一定要用与条件筛选的话,可以用#if语句做条件判定,这里不再赘述了。

至此,我们对Attributes的使用有了一个初步的认识。下一讲,我们将对Attributes的原理进行剖析。

Unity3D中的Attribute详解(一)的更多相关文章

  1. C#中的Attribute详解(下)

    原文地址:https://blog.csdn.net/xiaouncle/article/details/70229119 C#中的Attribute详解(下) 一.Attribute本质 从上篇里我 ...

  2. Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  3. 【Unity3D/C#】Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  4. js中的attribute详解

    Attribute是属性的意思,文章仅对部分兼容IE和FF的Attribute相关的介绍.attributes:获取一个属性作为对象getAttribute:获取某一个属性的值object.getAt ...

  5. .Net Attribute详解(下) - 使用Attribute武装枚举类型

    接上文.Net Attribute详解(上)-Attribute本质以及一个简单示例,这篇文章介绍一个非常实用的例子,相信你一定能够用到你正在开发的项目中.枚举类型被常常用到项目中,如果要使用枚举To ...

  6. .Net Attribute详解(一)

    .Net Attribute详解(一) 2013-11-27 08:10 by JustRun, 1427 阅读, 14 评论, 收藏, 编辑 Attribute的直接翻译是属性,这和Property ...

  7. Python中time模块详解

    Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...

  8. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  9. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  10. AngularJS select中ngOptions用法详解

    AngularJS select中ngOptions用法详解   一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...

随机推荐

  1. [自用初学]c++值传递和引用传递/ *&/ string

    https://baijiahao.baidu.com/s?id=1702573193376441989&wfr=spider&for=pc 总结: 1.函数参数传递主要分为值传递和& ...

  2. C# POST GET请求方式汇总

    /// <summary> /// POST方式提交 application/json /// </summary> /// <param name="post ...

  3. mysql 循环 例子

    mysql 循环生成数据demo: DROP PROCEDURE IF EXISTS test_insert; DELIMITER;; CREATE PROCEDURE test_insert() B ...

  4. Graphics绘制图形

    List<double> labels = form.channelData2[kp.Key]; List<double> listY = kp.Value; int labe ...

  5. Java工程结构 应用分层

    (一) 应用分层 1. [推荐]图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于 Web 层,也可以直接依赖于 Service 层,依此类推: • 开放接口层:可直接封装 Se ...

  6. C/C++ 异常处理机制(例:文件拷贝)

    异常是一种程序控制机制,与函数机制互补. 函数是一种以栈结构展开的上下函数衔接的程序控制系统,异常是另一种控制结构,它可以在出现"意外"时中断当前函数,并以某种机制(类型匹配)回馈 ...

  7. EL_获取域中存储的值_ List 集合&Map集合值和EL _ empty 运算符&隐式对象 pageContext

    3.获取对線. List 集合. Map 集合的值 1.对線:${域名称,键名.属性名}本质上会去调用对線的 getter 方法 2. List 集合:${域名称.键名[索引]} List list ...

  8. 生产环境出现CPU占用过高,分析思路和定位

    top 定位cpu占比高的pidjps -l 定位具体是后台哪个应用程序ps -mp 进程id -o(自定义格式) THREAD,tid,time 定位当前进程所有线程占用cpu时间高的线程idjst ...

  9. tensorflow2.0+TF-lite 各种报错

    generic_type: type "InterpreterWrapper" is already registered! 原因:tensorflow2.5.0rc0版本太高,降 ...

  10. verilog 概念版

    一.MCU芯片的定义 MCU芯片是指微控制单元(MicrocontrollerUnit:MCU),又称单片微型计算机或者单片机,是把中央处理器的频率与规格做适当缩减,并将内存.计数器.USB.A/D转 ...