首先来看一下微软官方对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. 零知识证明(Zero-Knowledge Proof)

    零知识证明(Zero Knowledge Proof)指的是,证明的人可以向验证的人,在不透露任何有用信息的情况下,使得验证者相信该结论是对的. 三种零知识证明技术:zk-SNARKs, Zk-STA ...

  2. Python 时间日期获取(今天,昨天或者某一段时间)

    日常使用的时间函数: 昨天,或者N天的日期 import time def time_stamp(days): hours = int(days) t = time.strftime("%Y ...

  3. js获取当前日期的前七天,月份+日(数组)

    1.定义一个空对象. let dayArr = []: 2.时间格式化  function formatterDate(date,fmt){     let nowDate = {       yyy ...

  4. Verilog语法+:的说明

    "+:"."-:"语法看到这个语法的时候是在分析AXI lite 总线源码时碰见的,然后查阅了资料,做出如下解释. 1.用处这两个应该算是运算符,运用在多位的变 ...

  5. LEETCODE 数组嵌套

    题目:数组嵌套 索引从0开始长度为N的数组A,包含0到N - 1的所有整数.找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以 ...

  6. OSIDP-虚拟内存-08

    硬件和控制结构 实际内存管理特点 1.一个进程可以在执行过程中换入换出内存,因而在内存中的位置可以不断变化. 2.一个进程可以划分为多个块,这些块位于内存中的地址不需要是连续的. 进程执行的任何时候都 ...

  7. STL练习-排列2

    Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input 每组数据占一行,代表四张卡片上的数字(0<=数字<=9 ...

  8. UIPath踩坑记一在浏览器控件中找不到”打开浏览器“控件

    问题:在浏览器控件中找不到"打开浏览器"控件 解决: 1.检查程序包中是否正常安装"UiPath.UiAutomation"包,如下图12.检查设计设置,是否关 ...

  9. 关系类处理专题之创建关系类|RelationShipClass

    /// <summary> /// 存在于数据库中的数据集中 /// </summary> /// <param name="mdbPath"> ...

  10. ssh双击互信

    默认公钥文件/root/.ssh/id_rsa.pub默认私钥文件/root/.ssh/id_rsa 只有将公钥文件文件拷到其他的服务器上才能登录别的服务器.   服务器A 192.168.1.133 ...