通过这篇文章,不仅可以了解到Attribute的工作原理,还可以了解到GetcustomeAttribute是的内部执行流程。最后,你会看到,使用缓存机制可以极大的优化反射Attribute的性能。

 

本文结构:

  1.为什么在对象上标记Attribute性能很慢。

  2.编译器如何编译带有Attribute标记的类型

  3.定义解析器,在运行时获取并解析对象上的Attribute

  4.GetCustomeAttributes方法的工作原理

  5.优化Attribute

  6.Attribute性能优化完整代码

  7.总结

 

参考资料:

关于Attribute的缓存思想请参见后面的链接,当然这篇文章里还介绍了依赖注入以及ORM中的一些优化,链接如下:http://www.codeproject.com/Articles/503527/Reflection-optimization-techniques

关于CustomeAttribute的介绍请参见ECMA-CLI文档第二部分Partition_II_Metadata的第22章第10节,但我再后面还是给出了这个介绍。

 

1.为什么在对象上标记Attribute性能很慢。

 首先请看如下代码:

   [TableAttribute("student")]

    class StudentModel {

        public string Id{get;set;}

    }

 

    class TableAttribute : Attribute {

        string name;

 

        public string Name {

            get { return name; }

        }

        public TableAttribute(string name) {

            this.name = name;

        }

    }

性能损耗1:每创建一个StudentModel对象,都要利用反射创建一个TableAttribute对象。

性能损耗2:上一步骤中创建的所有TableAttribute都是完全相同的,值都是”student”。换句话说,如果创建了n 个StudentModel,那么就会具有n个完全一样的TableAttribute。

 

2.编译器如何编译带有Attribute标记的类型

编译器在编译上述代码时,发现StudentModel有一个TableAttribute特性,就会在最终的程序集中生成一个customeAttribute元数据表,这个表有三个字段:parent,type,value。其中parent指向StudentModel类,type指向TableAttribute的构造函数,value值是要传递给TableAttribute的参数,这个里的参数就是”student”。如下图:

优化特性(Attribute)性能

3.定义解析器,在运行时获取并解析对象上的Attribute

如果对象上仅仅是标记了Attribute,那么是不会有什么性能损失的,因为我们并没有使用它。

每当我们自定义一个Attribute时,都要同时创建一个用于解析这个Attribute的解析器。这个解析器需要做两件事:第一获取对象上标记的Attribute,其次根据Attribute中的属性值来执行相应的动作。代码如下:

 class AttributeInterpreter {

        public static void Interprete() {

            TableAttribute[] attributes = typeof(StudentModel).GetCustomAttributes(typeof(TableAttribute), true) as TableAttribute[];

            foreach(var eachAttribute in attributes) {

                string tableName = eachAttribute.TableName;

                //根据tableName访问数据库中的对应表,然后读取数据并创建StudentModel对象。

            }

        }

    }

这里,首先获取StudentModel的Type,然后调用Type的GetCustomeAttributes方法,并传递了typeof(TableAttribute)参数。最后GetCustomeAttributes方法返回StudentModel上标记的TableAttribue对象。

附注:ECMA-CLI中的CustomeAttribute详细说明:

 

2 2 . 1 0   C us to mAt tr i b ut e : 0 x0 C
The CustomAttribute table has the following columns:
?  Parent (an index into  any metadata table, except the CustomAttribute table  itself; more precisely, 
a HasCustomAttribute    (§24.2.6) coded index)
?  Type (an index into the  MethodDef or MemberRef table; more precisely, a  CustomAttributeType 
(§24.2.6) coded index)
?  Value (an index into  the  Blob heap) 
Partition II  119
The CustomAttribute table stores data that can be used to instantiate a Custom Attribute (more precisely, an 
object of the specified Custom Attribute class) at runtime. The column called Type is slightly misleading—it 
actually indexes a constructor method—the owner of that constructor method is the Type of the Custom 
Attribute.
A row in the CustomAttribute table for a parent is created by the .custom attribute, which gives the value of 
the Type column and optionally that of the Value column (§21).
ECMA-CLI CustomeAttribute简介

相关文章:

  • 2022-02-15
  • 2021-06-29
  • 2021-11-07
  • 2021-11-13
  • 2021-08-01
  • 2021-11-09
  • 2021-04-09
  • 2021-07-12
猜你喜欢
  • 2021-05-18
  • 2021-11-14
  • 2021-06-22
  • 2021-12-08
  • 2022-02-12
  • 2021-09-09
相关资源
相似解决方案