首先来看一下微软官方对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. SQL之查询

    1. SQL之模糊查询 例如查询姓名时,不用输入全名,仅仅输入其中的一部分 语法: select 列名 from 表名 where 列名 like 匹配串 其中 匹配串用英文的单引号括起来 四种匹配模 ...

  2. React中的CSS模块

    CSS模块       使用步骤:         1.新建一个XXX.moudle.css文件         2.在组件中引入css           impor classes(变量) fro ...

  3. 解决Pycharm不能识别selenium的部分提示代码

    这是解决前,pycharm没有提示相关的webelement的代码,例如:send_keys, click 之类的 把鼠标指针放在 selenium 这个单词上就能看到这一串路径 然后找到这个路径的文 ...

  4. antv g6 出现 n.addEdge is not a function问题

    问题描述直接上图 解决方式就是将edge里面边的source和target对应的id换成字符串类型就行. 例如: edges: [ { id: 299, source": 3629.toSt ...

  5. pintia 3-7-5 逆波兰表达式求值 (20 分)

    3-7-5 逆波兰表达式求值 (20 分) 逆波兰表示法是一种将运算符(operator)写在操作数(operand)后面 的描述程序(算式)的方法.举个例子,我们平常用中缀表示法描述的算式(1 + ...

  6. Window10设置技巧

    1.关闭应用程序上的最近打开文件,效果图 2.固定到"开始"屏幕,效果图 3.任务栏图标太大了

  7. Learning under Concept Drift: A Review 概念漂移综述论文阅读

    首先这是2018年一篇关于概念漂移综述的论文[1]. 最新的研究内容包括 (1)在非结构化和噪声数据集中怎么准确的检测概念漂移.how to accurately detect concept dri ...

  8. 帝国CMS 登录后跳转ecmsadmin.php 白页 多个解决方案

    帝国CMS 6.6 版本, 运维的网站查询除了问题, 把网站数据库和整体网站拷贝到本地服务器, 配置好 e/config/config.php    和 e/class/config.php 两个目录 ...

  9. 2021.06.18 思科anyconnect安全移动客户端通知

    mac系统更新后,开关机后都会弹出思科anyconnect安全移动客户端通知的弹框,很烦,所以要干掉它! 打开终端,执行以下两行命令即可: cd /Library/LaunchAgents/ mv / ...

  10. python之自动化连连看脚本-第二关下移-小记

    (如想转载,请联系博主或贴上本博地址) 参考前一篇基础上,做出第二关下移逻辑判断,写的比较啰嗦. 下移和第一关不动基础代码是一样的.需要注意同列下移和不同列下移2种情况,同列下移需要注意相邻的2个和不 ...