先说说Attribute这个东西。
这次做需求第一次用,查找相关资料看的一脸懵逼,吐槽一手,这么简单的东西为啥要介绍的那么复杂。
Attribute叫特性,但是个人感觉把它当成标签理解更舒服点。
首先他是一个类,一个继承自System.Attribute的类。
他以[Attribute()]的形式标注在类啊,枚举啊,属性啊,方法之类上面,具体适用的对象:
[Attribute()]括弧就是这个Attribute的构造函数。
用法说完了,再说说它的作用:
先举个官方的例子,最后再说一个这次我自己用到的实例。
1、obsolete(预定义)
升级过U3D版本并且处理过Warning的同学应该对这个印象比较深刻,U3D在版本升级时通常会修改很多api(改名字或者改调用方式之类的),这时候它会用Warning告诉你,你这个api是旧的,新的要怎么怎么调。这个就是通过obsolete这个预定义的Attribute做的。
在每个方法里写LOG当然也可以实现,但是为了保持前端的一致性(比如来了新人),做该功能的人只需要在老api上加上这个“标签”就好了(后面就继续叫标签了,觉得这么理解舒服)。
2、自定义的Attribute
假如现在你手里有一堆对象,这些对象的类型不同,而且也没有共同的基类,但是它们有一个特点:这些类都实现了同一个接口。需求是,在某个地方调用这些对象的接口中的方法。
这就是Attribute登场的时候,自定义一个Attribute,给所有类实现这个方法的地方“贴上”咱们自定义的标签(在接口里贴不好使,查了官方文档,必须在具体实现的位置贴。。。),然后再调用的地方,通过反射筛选这些类的标签,然后再调用这个方法就好啦。
List<object> list = new List<object>();
MyManager myManager = new MyManager();
MineManager mineManager = new MineManager();
list.Add(myManager);
list.Add(mineManager);
假设MyManager和MineManager都实现了同一个接口,这个接口里有个Add()方法,这两个都实现了该方法,并且用MyAttribute标记过。
我们手里是List<object>队里,里面装了这两个类型的对象。
我们需要通过反射,拿到这些类中的方法信息,然后再调用这些对象的该方法即可。
for(int i = 0;i < list.Count;i++)
{
System.Reflection.MethodInfo[] methodInfos = list[i].GetType().GetMethods();
foreach(var methodInfo in methodInfos)
{
foreach(var attribute in methodInfo.GetCustomAttributes(typeof(MyAttribute),false))
{
MyAttribute myAttribute = attribute as MyAttribute;
if (myAttribute != null)
{
methodInfo.Invoke(list[i], null);
}
}
}
}
遍历该队列,拿到每个对象的Type,然后获取每个type的所有方法(因为我们的标签是加在方法上的),遍历所有方法,获取每个方法的所有Attribute,再遍历所有Attribute,找到MyAttribute类型的方法,调用就可以了(Invoke相关的不了解可以看之前的帖子)。