Attribute鲜为人知的两个特性记录

原文地址:点击打开链接

Attribute作为一种标记在我们的.net中随处可见,比如DatContract,DatMember,Serializable等等,各种用途的标记。是的我们的代码更加简洁,对于Attribute用好了,可以很好的简化我们的开发,比如PostSharp的AOP实现就是一种基于Attribute的标记编译时注入。在随笔中有关于IOC,AOP利用Attribute标记简化开发的实例。

   在使用Attribute时候发现了些鲜为人知的特性:

1:利用GetCustomAttributes传入的Attribute返回得到包括派生类。

2:GetCustomAttributes每次返回的对象都是经过发射出来的没有缓存。

   1:GetCustomAttributes传入的Attribute返回得到包括派生类:

       这里将采用一个测试类来验证:

复制代码
[AttributeUsage(AttributeTargets.Class)] 
   public  class TestImplementsAttribute : Attribute 
  { 
       public  string Name 
      {  getset; } 
  }

 

private  static  void TestMutilpeImplements() 

     var type =  typeof(Program); 
     var attrs = type.GetCustomAttributes( typeof(TestImplementsAttribute),  false); 
    Console.WriteLine( string.Format( " TestImplementsAttribute:({0}) ",attrs.Length)); 
     foreach ( var item  in attrs) 
    { 
        Console.WriteLine( "    " + item.GetType().FullName); 
    } 
    attrs = type.GetCustomAttributes( typeof(SerializableAttribute),  false); 
    Console.WriteLine( string.Format( " SerializableAttribute:({0}) ", attrs.Length)); 
     foreach ( var item  in attrs) 
    { 
        Console.WriteLine( "    " + item.GetType().FullName); 
    } 

    attrs = type.GetCustomAttributes( typeof(Attribute),  false); 
    Console.WriteLine( string.Format( " (base type)Attribute:({0}) ", attrs.Length)); 
     foreach ( var item  in attrs) 
    { 
        Console.WriteLine( "    " + item.GetType().FullName); 
    } 

}
复制代码

输出为: 

这里我们可以很清晰的看见当传入Attribute类型时候返回包含了SerializableAttribute和TestImplementsAttribute两个。

2:GetCustomAttributes每次返回的对象都是经过发射出来的没有缓存:

测试代码可以看出来,不是同一个地址引用:

复制代码
private  static  void TestAttributeActiver() 
      { 
           var type =  typeof(Program); 
           var attr1 = type.GetCustomAttributes( typeof(TestImplementsAttribute),  false)[ 0]; 
           var attr2 = type.GetCustomAttributes( typeof(TestImplementsAttribute),  false)[ 0]; 
          Console.WriteLine(Object.ReferenceEquals(attr1, attr2));            
      } 
复制代码

输出值为false。 

我们在看看

.下面是 reflector的反编译结果(Attribute.GetCustomAttributes):

View Code

在这里我们可以见数组的创建CreateInstance等等。

   同时可以参见老赵前辈以前的关于Attribute反射的一次失败的尝试(上):原来GetCustomAttributes方法每次都返回新的实例和一次失败的尝试(下):无法使用泛型的Attribute。

   不知道为什么在Attribute参数的检查是在我们的编译时期,参数必须是常量表达式,却在这里需要每次反射。

   本篇随笔只是个人使用心得记录,请勿拍砖。

你可能感兴趣的:(Attribute鲜为人知的两个特性记录)