之前写代码会经常看到获得 unity 组件 我也就一直在用也没了解下背后的秘密 这是记事本写上了这种用法 今天不知道摸鱼不香了 还是闲的蛋疼了 想要了解下这个背后的原理
[UIControl("normal/Back/Title/Text")]
protected Text TitleText;
探秘阶段一#
先找打实现的方法
public class UIControlAttribute : Attribute
{
public string controlName;
public System.Type componentType;
public int baseNum;
public UIControlAttribute(string controlName,System.Type componentType = null,int baseNum = 0)
{
this.controlName = controlName;
this.componentType = componentType;
this.baseNum = baseNum;
}
}
第一印象 是一个继承了 c# 的特性
然后就是这是如何获取的了?我当时是一头雾水
貌似就要了解下 c# 特性了
探秘阶段 二#
看这位老师介绍说 还挺形象的 简单地说,Attribute 就是一种 “附着物”—— 就像牡蛎吸附在船底或礁石上一样
Attribute 是一种可由用户自有定义的修饰符(Modifier),可以用来修饰各种需要被修饰的目标。我们可以对类、以及 C# 程序集中的成员进行进一步的描述。
有点像 python 里面的装饰器 都是对类 以及方法的 再次描述
与注释的本质区别就是不会被 丢弃#
Attribute 是程序代码的一部分,它不但不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里。在程序运行的时候,随时可以从元数据(元数据:.NET 中元数据是指程序集中的命名空间、类、方法、属性等信息,这些信息是可以通过 Reflection 读取出来的。)中提取提取出这些附加信息,并以之决策程序的运行。
下面是上面老师给出一个简单示例#
比如我们写一个关于人的类 Person,该类可以对人的属性以及某些行为 (方法) 进行描述。那么如果我们要对人类进行进一步描述呢?比如人这个类是属于动物的灵长类动物 当然有人会说我们可以为这个 Person 类去写一个灵长动物类的父类,再用人类去继承这个类去解决。但是我们要求的是仅仅是描述性的,就是对这个人类进行进一步的描述,而在实际操作中不需要去操作。这样的情况我们就可以用特性的概念去解决,特性简而言之就是程序集的特定程序元素所具有的另外的性质。
//先定义一个人类Person类
class Person
{
//人的姓名储存字段和属性
private string name;
public string Name
{
set { name = value; }
get { return name; }
}
//人的年龄储存字段和属性
private int age;
public int Age
{
set { age = value; }
get { return age; }
}
//人的性别储存字段和属性
private char sex;
public char Sex
{
set { sex = value; }
get { return sex; }
}
//人的打招呼方法
public void SayHello()
{
Console.WriteLine($"大家好,我叫{this.Name},我今年{this.Age}岁了,我的性别是{this.Sex}");
}
}
后再定义一个一个灵长类的特征
//定义动物的特性类AnimalAttribute类继承于Attribute(特性)
class AnimalAttribute : Attribute
{
//字段和属性描述是否是灵长类
private bool isPrimate;
public bool IsPrimate
{
set { isPrimate = value; }
get { return isPrimate; }
}
}
对人类进行动物类描述。即在人类的定义前面加:
[Animal (IsPrimate = true)] // 为人类加特性,指定人类是灵长类。
[Animal(IsPrimate = true)]
class Person
后面我们即可通过反射的方法来回去特性
//声明特性对象,并通过Attribute类的静态方法GetCustomAttribute()获得人类的在动物类的特性,并赋值给特性对象
Attribute att1 = Attribute.GetCustomAttribute(typeof(Person), typeof(AnimalAttribute));
//将特性对象转化为动物特性对象
AnimalAttribute animalAtt = att1 as AnimalAttribute;
//检查转化是否成功如果成功则打印这个特性对象的是否是灵长类的属性。
if (animalAtt != null)
{
Console.WriteLine("人类是否是灵长类:{0}", animalAtt.IsPrimate);
}
Console.ReadKey();
举一反三#
我想到之前遇到一个问题 让一个方法返回字符串 变成大写的 完全就可以通过这样的方式来进行调整
有劳 GPT 帮我写份代码了
using System;
using PostSharp.Aspects;
[Serializable]
public class ToUpperCaseAttribute : MethodInterceptionAspect
{
public override void OnSuccess(MethodExecutionArgs args)
{
if (args.ReturnValue is string returnValue)
{
args.ReturnValue = returnValue.ToUpper();
}
}
}
public class MyClass
{
[ToUpperCase]
public string GetUpperCaseString(string input)
{
return input;
}
}
class Program
{
static void Main(string[] args)
{
var myClass = new MyClass();
string result = myClass.GetUpperCaseString("Hello, World!");
Console.WriteLine(result); // Output will be "HELLO, WORLD!"
}
}
MethodInterceptionAspect
允许你在方法执行的不同阶段插入自定义的代码。
OnSuccess 方法: OnSuccess
是在方法成功完成后被调用的方法。你可以在这个方法中访问方法的返回值并进行操作。在上面的示例中,我们使用 OnSuccess
方法将方法返回的字符串转换为大写。
探秘阶段 三#
知道原理以后全局搜索下如何获取自然 而然找到了初始化面板控件里面
有对 UI 的操作 疑惑就解除了
此文由 Mix Space 同步更新至 xLog
原始链接为 http://121.41.123.51:2333/posts/categories/3